python面试题
1. 面试总结
先把这个看了,总结的很全面
https://www.cnblogs.com/JetpropelledSnake/p/9396511.html
3. 零碎
1. 类继承的super()原理
Python中每一个类都有一个MRO列表,他代表了类的继承顺序,super会返回当前类index+1的类,然后按照此顺序分别去执行他们的方法,知道最后的base类
2. 单例模式
线程锁+__new__来实现
__new__(cls,*args,**kwargs)中判断当前类是否有实例(cls.instance是否为真),没有就开线程锁,然后创建,有的话,就返回当前实例
3. 类的常用方法及解释
__dict__ 以字典的格式返回实例的属性
__call__ 使实例可以像函数一样加括号被调用,也可以传参数
__new__ # 创建类时,先执行此方法,返回一个实例,再执行__init__
__getitem__ 实例动态的获取属性的值
__setitem__ 实例可以动态的添加属性
__delitem__ 删除值
__enter__ # 上下文管理,见4
__exit__ # 上下文管理,见4
__setattr__ 用于注册实例的属性,即
__str__ print时会调用
示例:
__setitem__(self,key,value):
__new__(cls,*args,**kwargs)
4. 上下文管理实现机制
调用__enter__返回一个文件对象
执行完成之后自动调用__exit__,关闭文件
5. Python2,3的区别
主要区别,
1. 编码问题:2是ascii编码,3是utf8编码。
2. 整数除法问题:2的整数相除得到整数,3得到浮点数
6. 垃圾回收机制与GRL锁
垃圾回收机制:
引用计数:
变量值每被引用1次,计数加一,当引用计数为0时,变量值就会被解释器清除
循环引用(引用计数存在的缺陷):两个列表相互引用,引用计数永远不为0
标记清除:
当内存达到一定程度时,Python程序停止运行,启动标记清除算法。
先确定一个肯定不会被清除的变量,然后能够被他直接或间接访问到的标记为存活对象(不会被删除的变量,继续对其扫描),然后依次扫描,将不是存活对象的都清除掉
分代回收:
在经历多次扫描的情况下,都没有被回收的变量,认为它是常用变量,对其的扫描频率降低
新生代:新定义的变量, 假设每5分钟扫描一次
青春代:从新生代过来的变量, 假设10分钟扫描一次
老年代:从青春代过来的变量,假设30分钟扫描一次
GIL全局锁:
GIL锁仅针对CPython解释器
每个进程中的线程必须获得这个锁才能获得cpu等资源,然后执行,这导致了python同一进程下的线程不能使用多核同时执行
8. 常用模块
1. 爬虫相关:requests, BS4,selenium,
2. 图片处理:pillow
3. 日历calendar,chinesecalendar
4. 连接数据库:pymysql
5. 数据分析包:numpy, pandas, matplotlib
6. re
7. xlwt,xlrd
8. datetime
9. traceback
10. os
9. 对于Python的理解
Python 是一种面向对象、解释型语言
代码简洁,写起来很快,很多第三方包
速度很慢
10. 进程,线程,协程
1. 线程锁
python中有两种线程锁,Lock和Rlock,Lock不能多层嵌套,获取到一次,必须释放一次才能获取下一次锁。但是Rlock可以连续获取多次锁,然后只需多次释放锁即可
单例模式,加线程锁
2. 进程
多进程时:windows中启动方式是spawn,系统会新开一个解释器,然后从主进程复制必要的资源(能够让进程启动的资源),主进程与子进程管理各自的资源,互不干扰。
在linux中,开启一个子进程,子进程会复制几乎所有的主进程的资源,主进程与子进程管理各自的资源,互不干扰
。
11. 迭代器与生成器
12. 数据结构
13. 架构设计
https://github.com/xitu/system-design-primer#additional-system-design-interview-questions
14. mysql与pg的主要区别
pg对于数据的准确性,一致性执行较好。
mysql因为缺少上面的校验,性能较好
pg是多进程,mysql是多线程
pg支持json格式的存储
15, 读文件
为了不占用内存,推荐使用for,一行一行读 with open(path, 'rb') as infile: for line in infile: print(line)
16. lambda函数
def multipliers(): return [lambda x:i*x for i in range(4)] print([m(2) for m in multipliers()]) #解释: 函数返回值为一个列表表达式,经过4次循环结果为包含四个lambda函数的列表, 由于函数未被调用,循环中的i值未被写入函数,经过多次替代,循环结束后i值为3, 故结果为:6,6,6,6
列表生成式返回的是列表,列表生成器返回的是生成器,使用的时候一次一次的调用。区别是一个是[],一个是()
请修改multipliers的定义来产生期望的结果(0,2,4,6)。
def multipliers():
return (lambda x:i*x for i in range(4)) #返回一个生成器表达式
print([m(2) for m in multipliers()])
17.实现一个栈
# 实现一个栈stack,后进先出 ''' class Stack: def __init__(self): self.items = [] def is_empty(self): # 判断是否为空 return self.items == [] def push(self,item): # 加入元素 self.items.append(item) def pop(self): # 弹出元素 return self.items.pop() def peek(self): # 返回栈顶元素 return self.items[len(self.items)-1] def size(self): # 返回栈的大小 return len(self.items) if __name__ == "__main__": stack = Stack() stack.push("H") stack.push("E") stack.push("L") print(stack.size()) # 3 print(stack.peek()) # L print(stack.pop()) # L print(stack.pop()) # E print(stack.pop()) # H '''
18装饰器
@functools.wraps(func)
19. yield
作为函数的返回值,每次调用返回一个值,然后阻塞,等待下一次调用。
协程会用到
参考:http://events.jianshu.io/p/dda2003e1aa2
20. 定时任务APschduler
参考:https://zhuanlan.zhihu.com/p/491679794
21. mysql死锁解决
1. 设计程序时,按照同一个顺序去获取锁 2. 加锁的时候,尽量将所有需要用到的资源一起加锁 3. 事务的持续时间尽可能的短
22. 类的三大特性
1. 继承,子类继承父类的属性,代码复用 2. 封装,将属性和方法封装在类内,封装的属性会有私有,受保护,公有三种 3. 多态,子类可以重写父类的方法
23. 上下文管理
写程序进行资源操作的时候,用完要及时释放,不然会造成资源泄露,就是资源一直被占着
参考:https://blog.csdn.net/qdPython/article/details/124198593