python基础面试题

前言

写博客的第二篇:
为什么要写这篇文章?因为这是作者所经历过的面试,一鼻子的灰,作者一直想找数据分析的工作,可只会简单的爬取,知道爬虫思路,当被问到基础的东西时,就突然一脸懵逼,咦?这个我好想用过啊!是怎么来着?也过于紧张,在面试的时候双脚抖得疼痛。以python的对象来说,大脑是对象,还是空白的那种。面试某公司,面试官让我买本书看看!深受打击,在面试的前一晚,作者复习爬虫到3点,之后就被基础的知识问傻了,人也傻了。写这篇文章,也在于激励自己,绝不放弃,也希望能给各位一些小经验,基础!基础!基础!

字典

字典相加合并


dict_a = {'a':'这是字典a','b':'这是字典b'}
dict_b = {'c':'这是字典c','d':'这是字典d'}
merge_dict = dict(list(dict_a.items())+list(dict_b.items()))
print(merge_dict)
#输出{'a':'这是字典a','b':'这是字典b','c':'这是字典c','d':'这是字典d'}

这里使用了items方法,何为items方法呢?Python 字典items() 函数以列表返回可遍历的(键, 值) 元组数组。这是网上解释,作者分解一下,请看!

dict_a = {'a':'这是字典a','b':'这是字典b'}
c = dict_a.items()
print(c)
print(type(c))
#输出dict_items([('a', '这是字典a'), ('b', '这是字典b')])
#输出<class 'dict_items'>

对了!返回的不是列表,而是’dict_items’,而这里要合并需将’dict_items’转换为’list’。list(dict_a.items())+list(dict_b.items())就相当于两个列表合并,再转换为字典,相信你脑海已经有结果。

dict()合并字典

dict_a = {'a':'这是字典a','b':'这是字典b'}
dict_b = {'c':'这是字典c','d':'这是字典d'}
merge_dict = dict(dict_a,**dict_b)
print(merge_dict)
#输出{'a': '这是字典a', 'b': '这是字典b', 'c': '这是字典c', 'd': '这是字典d'}

这是dict方法,dict()函数用于创建一个字典。用法可以自行上网搜一下。

列表

列表合并相加

list_a = ['a','b']
list_b = ['c','d']
merge_list = list_a+list_b
print(merge_list)
#输出['a', 'b', 'c', 'd']

这个就简单的两个列表相加。

extend()方法合并

list_a = ['a','b']
list_b = ['c','d']
list_a.extend(list_b)
print(list_a)
#输出['a', 'b', 'c', 'd']

extend()该方法没有返回值,但会在已存在的列表中添加新的列表内容。

列表字典转换

列表转字典

l1 = ['a','b']
l2 = [1,2]
z1 = zip(l1,l2)#这里方便理解分开写了
z = dict(z1)
print(z1)
print(z)
print(type(z1))
'''输出
<zip object at 0x0000028318EF40C8>
{'a': 1, 'b': 2}
<class 'zip'>
'''

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
那为什么打印出print(z)是<zip object at 0x0000028318EF40C8>这个玩意呢?
再来看看

l1 = ['a','b']
l2 = [1,2]
z1 = list(zip(l1,l2))#这里方便理解分开写了
print(z1)
#输出[('a', 1), ('b', 2)]

zip()函数打印出来的就是这样,再加个 dict(z1)也就转换为字典了。

字典转列表

dict_1 = {'a': 1, 'b': 2}
a = list(dict_1.keys())
b = list(dict_1.values())
print(a)
print(b)
'''输出
['a', 'b']
[1, 2]
'''

字典就是键值对,分别取出字典的键和值转换为列表就行了。

切片使用

题目

输入字符串’123456789’,想提取出2468,13579。

解答一

s = '123456789'
return_s = s[0:10:2]
print(return_s)
return_s1 = s[1:10:2]
print(return_s1)
#输出13579
#输出2468

这是切片的使用,start : end : step
其实位置:start
末尾位置:end
步长:step

解答二

s = '123456789'
a = []
b = []
for i in range(len(s)):
    if int(s[i])%2 ==0:
        a.append(s[i])
    else:
        b.append(s[i])
print(a)
print(b)
#a输出['2', '4', '6', '8']
#b输出['1', '3', '5', '7', '9'] 

这里采用了余数的计算方法,当然和切片使用没有关系,只是根据题目而言,这里这是做简单的操作。

装饰器

装饰器概念及用途

装饰器本质上还是函数,可以让其他函数在不做任何代码修改的前提下增加额外功能,它通常用于切面需求,例如:插入日志、性能测试、权限校验等。

写一个装饰器(题目)

def f2(func):
    def f1():
        return func()+1
    return f1
@f2
def func():
    print('func()函数')
    return 1
print(func())
'''输出
func()函数
2
'''

通过@符号和装饰器名实现装饰器函数与被装饰器函数联系。再说一遍,‘让其他函数在不做任何代码修改的前提下增加额外功能’。

不要装饰器,代码是这样的👇

def f2(func):
    def f1():     #闭包
        return func()+1
    return f1
def func():
    print('func()函数')
    return 1
a = f2(func)
print(a()) 

装饰器的本质就是一个嵌套函数,外层函数的参数是被修饰的函数,内层函数是一个闭包并在其中增加新功能(装饰器的功能函数)。

生成器与迭代器

生成器

生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。

import sys
def f2():
    a = 0
    while a<5:
        yield a
        a += 1
b = f2()
while True:
    try:
        print(b.__next__(),b)
    except StopIteration:   #StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况。
        sys.exit()
'''输出
0 <generator object f2 at 0x0000021BA724D848>
1 <generator object f2 at 0x0000021BA724D848>
2 <generator object f2 at 0x0000021BA724D848>
3 <generator object f2 at 0x0000021BA724D848>
4 <generator object f2 at 0x0000021BA724D848>
'''

生成器相比一次列出所有内容的优势:
1.更节省存储空间
2.响应速度更快
3.使用更加灵活

迭代器

什么是迭代器?
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。
迭代器只能往前不会后退。

迭代器有两个基本的方法:iter() 和 next()。

l=[1,2,3,4]
it = iter(l)    # 创建迭代器对象
for x in it:
    print (x, end=" ")
#输出1 2 3 4

```#next()用法
l=[1,2,3,4]
it = iter(l)    # 创建迭代器对象
print(next(it))
print(next(it))
print(next(it)) 
print(next(it))

生成器与迭代器的区别

生成器是一种特殊的迭代器,生成器能做迭代器能做的所有事,使用生成器表达式取代列表解析可以同时节省内存资源。生成器终结时还会抛出StopIteration异常。

实例、静态、类方法

实例方法

实例方法:()里面的第一个参数必须是实例对象,一般约定为self通过它来传递实例属性和方法。

class student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def info(self):   #实例方法
        print('{}已经{}岁了!'.format(self.name,self.age))
a = student('csdn',100)  #传参
a.info()

静态方法

使用装饰器@staticmethod,它在其中只是起到帮助的信息,存放逻辑代码,它是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。()内不用加self或者cls!!

class student:
    @staticmethod
    def info():  #静态方法
        print('帮助理解')
a = student()
a.info()
#输出 帮助理解
'''
这里只是简单的介绍一下,不要太注重细节,哈哈
'''

注意:静态方法不能访问类属性!!

类方法

使用装饰器@classmethod,()内的参数与实例方法参数self不一样,类方法的是cls。

class student:
    r = '这是类方法'
    @classmethod
    def info(cls): #类方法
        print(cls.r)
a = student()  #创建对象
a.info()
#输出  这是类方法

注意:类方法可以访问类属性。

单例模式

什么是单例模式?
创建的对象使用的是同一地址。

题目

写出至少两种以上的单例模式!

基于__new__(推荐)

class student:
    __instance = None  #私有化,设置__instance为空
    def __init__(self):
        pass
    def __new__(cls):
        if cls.__instance is None:  #判断是否为空
            cls.__instance = object.__new__(cls) #使用__new__开辟一个新地址
            return cls.__instance
        else:  #若不为空
            return cls.__instance #直接返回已有的地址
s = student()  #先调用__new__再调用__init__。
s1 = student()
print(s)
print(s1)
'''输出
<__main__.student object at 0x00000187885A7D48>
<__main__.student object at 0x00000187885A7D48>
'''

一下是多线程使用的单例模式👇方法就和上面👆所说的一样,只是加了多线程

import threading
class Singleton(object):
    _instance_lock = threading.Lock()
    def __init__(self):
        pass
        
    def __new__(cls,*args,**kwargs):
        if not hasattr(Singleton,'_instance'):
            with Singleton._instance_lock:
                if not hasattr(Singleton,'_instance'):
                    Singleton._instance = object.__new__(cls)
        return Singleton._instance

def task(args):
    obj = Singleton()
    print(obj)
for i in range(4):
    t = threading.Thread(target=task,args=[i,])
    t.start()

基于类方法

import threading
class Mysingle(object):
    _instance_lock = threading.Lock()
    def __init__(self):
        pass
    @classmethod
    def instance(cls,*args,**kwargs):
        if not hasattr(Mysingle,'_instance'):
            with Mysingle._instance_lock:
                if not hasattr(Mysingle,'_instance'):
                    Mysingle._instance = Mysingle(*args,**kwargs)
        return Mysingle._instance

def task(args):
    single = Mysingle.instance()
    print(single)
for i in range(4):
    t = threading.Thread(target=task,args=[i,])
    t.start()

工厂模式

什么是工厂模式?
工程模式主要用来实例化有共同方法的类,它可以动态决定应该实例化哪一个类,不必事先知道每次要实例化哪一个类。

例如在编写一个应用程序时,用户可能会选择连接各种各样的数据库,但开发者不能预知用户会使用哪一个数据库,于是提供一个通用的方法,里面包含了各个数据库的连接方案,用户在使用过程中,只需要传入数据库的名字并给出连接所需要的信息即可。

class Operation(object):
    def connect(self):
        pass
class MYSQL(Operation):
    def connect(self):
        print('连接MYSQL成功')
class SQLite(Operation):
    def connect(self):
        print('连接SQLite成功')
class DB(object):
    @staticmethod
    def create(name):
        name = name.lower()
        if name == 'mysql':
            return MYSQL()
        elif name == 'sqlite':
            return SQLite()
        else:
            print('不支持其他数据库连接')

db1 = DB.create('MYSQL')
db1.connect()
db2 = DB.create('SQLite')
db2.connect()

DB类定义了一个静态方法create(),该方法的参数为类名,可以根据类名创建对应的对象,因此称为工厂方法。

小结

这是作者目前面试所遇到的一些题目,仅供参考,当然还有其他的,例如之前写过的基础算法(可以去看之前写过的python基础算法文章)。这些都是基础的,走开发方向的话,单例模式,多线程这些一定要弄明白。
面试官会经常问:你还有什么要问的吗?
根据自己的情况如实回答,包括薪资、住宿、生活方面的都可以问(表明的你诚意,是想要去的,也防止后面因为某些原因!)。还需加上一点,我能学到什么?能有什么发展?(表明你有上进心)或者可以说公司对人才培养方面有什么计划呢?就是之类的。

面试需要运气:
面试也是需要运气的,为什么这么说呢?就拿一个简单的例子,面试官会问你 "你需要多少薪资呢?"侧面来说你觉得你的能力能值多少?能为公司创收多少价值?说少了面试官又觉得你能力不行,说多了吧,面试官又觉得太高。按网上说:“我相信贵公司有一套完整的新人体系,我愿意接收这一套体系”。又觉得假。那怎么办?运气,面试官心情,个人决定。再比如,面试官问的问题,刚好涉及你的知识盲区,那岂不是凉了,作者就被面试官问到了基础不常用的知识盲区,就凉了,当时是早上一场面试,下午一场面试,早上的知识盲区了,下午问的,哎!就是我懂的,都能回答上来——scrapy的运行机制、你什么怎么爬取网站过程的,遇到过哪些问题?如何解决?老板!我会啊!这就是运气了!关于上面这几个问题大家可以上网搜一下,作者后续也可能会发相关的文章。仅仅一点点经验,也还是分享一下,大佬路过方便的话也希望留下一些东西,路在脚下,我在成长。遇到挫折不要退缩,面试题涉及到你的知识盲区,就去学习!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值