目录
- 01 函数传参
- 02 类&对象&静态方法
- 03 类&对象变量
- 04 自省
- 05 推导式
- 06 下划线
- 07 可迭代对象 VS 迭代器 VS 生成器
- 08 枚举enumerate
- 09 *args&*kwargs
- 10 装饰器(decorator)
- 11 鸭子类型(像=是)
- 12 函数重载
- 13 新式类&旧式类
- 14 new vs init
- 15 单例模式(面试常考)
- 16 作用域
- 17 协程
- 18 闭包(closure)
- 19 lambda
- 20 函数式编程(filter,map,reduce)
- 21 浅拷贝&深拷贝
- 22 整数范围
- 23 垃圾回收机制
- 24 is
- 25 read & readline & readlines
- 26 range & xrange
- 27 python2 VS python3
- 28 list
- 29 超类super
- 30 eval()
- 31 内核态 & 用户态
- 32 各种锁
- 33 python运行过程
- 34 魔法
- 45 collections
- 46 异常
- 47 跳出双重循环
- 48 检查对象的内存占用情况
- 参考
01 函数传参
python一切皆对象,分为2类:
(1)num,str,tuple 不可更改
(2)list,dict,set 可更改
函数传参时,传的是引用,第一类不会变,第二类会变
02 类&对象&静态方法
python有3个方法:
(1)实例方法
self 绑定实例——》foo(self,x)
(2)类方法
cls 绑定类——》class_foo(cls,x)
(3)静态方法
不需要绑定——》 classname(objectname).func
A.static_foo(x) a.static_foo(x)
03 类&对象变量
实例变量:只属于单个实例——》self.变量名
类变量:对于所有实例是共享的——》classname.var
04 自省
在运行时,能知道对象类型
- type() :返回对象类型(不考虑继承)
- dir() :返回模块的变量、方法和定义的类型列表
- getattr(对象,属性) :返回对象属性的值
- hasattr(对象,属性) :检查对象是否有属性值
- isinstance(对象,类型) :检查对象是否是该类型(考虑继承)
inspect模块
05 推导式
(1)字典推导式
d = {k:v for k,v in zip(list1,list2)}
快速对换键,值对
(2)集合推导式
和列表推导式,最大的不同,用大括号
06 下划线
单前导下划线:_var # 半私有,可被外部访问
单末尾下划线:var_ # 避免命名冲突
双前导下划线:__var # 私有,不可以被外部访问
双前导和末尾下划线:__var__ # 魔术方法,内置属性名
单下划线:_ # 临时/无关紧要的变量
私有 self.__head = None
双下划线:解析器用_classname__fuc区分和其他类相同的命名
07 可迭代对象 VS 迭代器 VS 生成器
(1)可迭代对象:
有__iter__()方法
如:str,list,tuple,set,dict
(2)迭代器
有__iter__()方法 和 next()方法
迭代结束,跑出StopIteration异常
(3)生成器
有yield,iter()方法 和 next()方法
可以从外部用send给yield传值
用iter()函数,可以将可迭代对象转为迭代器
return和yield的区别: 都可以返回1个/多个值 return返回1次,yield返回多次
- 迭代器:存储的 ,可循环多次,用next(i)遍历,超出范围则抛出异常
li = [x*x for x in range(10)] # li是可迭代对象(iter)
i = itr([x*x for x in range(10)]) # i是迭代器对象(iter,next)
- 生成器(特殊迭代器):实时的,只能循环1次
g = (x*x for x in range(10))
iter()
对可迭代对象,返回其迭代器的实例
对迭代器,返回自身self
class MyList(object):
## 定义可迭代对象类
def __init__(self, num):
self.data = num # 上边界
def __iter__(self):
return MyListIterator(self.data) # 返回该可迭代对象的迭代器类的实例
class MyListIterator(object):
## 定义迭代器类,是MyList可迭代对象的迭代器类
def __init__(self, data):
self.data = data # 上边界
self.now = 0 # 当前迭代值,初始为0
def __iter__(self):
return self # 返回该对象的迭代器类的实例;因为自己就是迭代器,所以返回self
def next(self): # 迭代器类必须实现的方法
while self.now < self.data:
self.now += 1
return self.now - 1 # 返回当前迭代值
raise StopIteration # 超出上边界,抛出异常
my_list = MyList(5) # 得到一个可迭代对象
print type(my_list) # 返回该对象的类型
my_list_iter = iter(my_list) # 得到该对象的迭代器实例
print type(my_list_iter)
for i in my_list: # 迭代
print i
## 定义生成器
def myList(num):
now = 0 # 当前迭代值,初始为0
while now < num:
val = (yield now) # 返回当前迭代值,并接受可能的send发送值,yield可以理解为不释放函数的return
now = now + 1 if val is None else val # val为None,迭代值自增1,否则重新设定当前迭代值为val
my_list = myList(5) # 得到一个生成器对象
print my_list.next() # 返回当前迭代值
print my_list.next()
my_list.send(3) # 重新设定当前的迭代值
print my_list.next()
print dir(my_list) # 返回该对象所拥有的方法名,可以看到__iter__与next在其中
https://blog.csdn.net/liangjisheng/article/details/79776008
08 枚举enumerate
for idx,val in enumerate(li):
print(idx,val)
09 *args&*kwargs
*args:参数数量不定(列表)
**kwargs:参数名不定(字典)
*args必须在**kwargs前面
li = [1,2,3]
func(*li )解释器自动解包,传入多个参数《——》func(1,2,3)
10 装饰器(decorator)
为已存在的对象,添加额外的功能
将函数func作为参数,传给另一个函数,返回修改后的自己
应用场景:插入日志、性能测试、事务处理
https://www.runoob.com/w3cnote/python-func-decorators.html
斐波那契记忆化递归写法:
def memo(func):
cache = {}
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
@memo
def fib(n):
if n<2:
return 1
return fib(n-1)+fib(n-2)
11 鸭子类型(像=是)
行为像鸭子,就认为它是鸭子
list.extend(鸭子):这个鸭子可以是list,tuple,dict,str,generator等可迭代的
12 函数重载
(i)函数功能相同,(ii)参数类型不同,(iii)参数个数不同。
(i)+(ii):不需要处理(python可接受任何类型参数)
(i)+(iii):缺省函数(缺少的参数设成缺省参数)
因此,python不需要函数重载
13 新式类&旧式类
- 新式类: 从左到右,宽度优先 (C3算法)
- 旧式类: 从左到右,深度优先 (子类重写,会被绕过)
(子类越过父类,子类重写父类构造——》报错)
继承object的是新式类
14 new vs init
- new创建对象,init初始化对象
- new返回对象,init无返回
- new的调用在init之前,是静态方法
- new是类级别的(至少有个参数cls),init是对象级别的(至少有个参数self)
cls表示要实例化的类
__new__
__init__
- new的应用:
继承不可改变类时,重载new,自定义以改变对象实例化过程
15 单例模式(面试常考)
类只有一个对象
创建单例时,只执行1次init方法
class Singleton(object):
__instance = None # 私有属性
def __new__(cls,age,name):
if not cls.__instance: # 无类对象,或类对象无值
cls.__instance = object.__new__(cls) # 创建对象,赋值为对象的引用
return cls.__instance # 如果有,就直接返回
def __init__(self,age,name):
if not self.__first_init:
self.age = age
self.name = name
Singleton.__first_init = True
a = Singleton(18,"xxx")
b = Singleton(8,"xxx")
print(id(a),id(b)) #两个id是一样的
print (a.age,b.age) # a,b指向的对象属性一样
a.age = 19
print(b.age) # b指向的对象属性和a一样
(1)使用new方法
(2)共享属性
创建对象时,把所有对象的__dict__指向同一个字典
对象具有相同的属性和方法
(3)装饰器版本
(4)import方法
import的模块是天然单例模式
作用:节约系统资源
应用:回收站
16 作用域
- 变量作用域:在被赋值的地方决定
- 遇到变量,搜索顺序:
local——》enclosing locals——》gloabl——》built-in
local:本地作用域
enclosing locals:当前作用域被嵌入的,本地作用域
gloabl:全局/模块作用域
built-in:内置作用域
global:在函数中,使用全局变量
nonlocal:在内嵌函数中,使用外部函数的变量
17 协程
进程、线程的升级版
进程&线程:内核态,用户态切换问题,耗费时间
协程:用户控制切换时机,不陷入内核态
yeld是协程
18 闭包(closure)
语法结构,组织代码的结构,提高复用性
产生条件:
(1)内嵌函数
(2)内嵌函数引用外部函数的变量
(3)外部函数返回值是内嵌函数
函数运行后,不能被销毁,继续留在内存
19 lambda
==lambda表达式=匿名函数 ==
lambda 输入:输出
lambda x : x**2
lambda x,y : x+y
20 函数式编程(filter,map,reduce)
- filter:过滤器,只留下满足filter条件的
filter(lambda x : x>1, [1,2,3]) # 返回[2,3]
- map:对序列依次执行
map(lambda x: x*2, [1,2,3]) # 返回[2,4,6]
- reduce:对序列依次迭代调用
reduce(lambda x,y : x+y, [1,2,3]) # 返回1+2+3=6
其中[1,2,3]可以换成range(1,4)
21 浅拷贝&深拷贝
列表是可变类型
原始列表:
li = [1,2,3,[‘a’,‘b’]]
改变列表:
li.append(100) # 改变对象li
li[3].append(‘c’) # 改变对象li的list对象[‘a’,‘b’]
最终列表:
li = [1,2,3,[‘a’,‘b’,‘c’],100]
-
赋值:完全相同,跟着变
li2 = li
li2 = [1,2,3,[‘a’,‘b’,‘c’],100] -
浅拷贝:部分相同,只能变对象的对象
li3 = copy.copy(li)
li3 = [1,2,3,[‘a’,‘b’,‘c’]] -
深拷贝:完全不同,不会变
li4 = copy.deepcopy(li)
li4 = [1,2,3,[‘a’,‘b’]]
22 整数范围
-2147483648 < int < 2147483648
长整数:25L
23 垃圾回收机制
引用计数+分代回收。引用计数为主。
原理:每一个对象都记住有多少其他对象引用了自己,当没有人引用自己的时候,就是垃圾了。
-
引用计数(reference counting):跟踪和回收垃圾
对象有新引用,ob_refcnt + 1
对象被删除,ob_refcnt - 1
ob_refcnt = 0,对象生命结束
简单,实时;维护ob_refcnt 消耗资源,循环引用 -
标记-清除(mark and sweep):解决容器对象可能产生的循环引用问题
按需分配
没空闲内存,从寄存器和程序栈上的引用出发,遍历图(节点=对象,引用=边),可访问的标记,清扫内存,没标记的对象释放 -
分代回收(generation collection):空间换时间,提高回收效率
内存块按存活时间划分到不同集合(代)
代存活时间越长,垃圾收集频率越低
默认定义3代
24 is
is:对比地址
==:对比值
25 read & readline & readlines
read:读整个文件
readline:读下一行,用生成器
readlines:读整个文件,放入迭代器
26 range & xrange
range:返回list,数据全部生成取出,存在内存中
返回一个list,是可迭代对象,不是迭代器
经过iter()可转为列表迭代器
xrange:生成器,数据生成一个取出一个,内存性能更好
返回一个序列,是可迭代对象,不是迭代器
经过iter()可转为范围迭代,用next()取出
python3只有range() 和python2中的xrange一样
27 python2 VS python3
28 list
29 超类super
重写:继承机制,构造方法
构造方法:初始化对象的状态
子类:自己的初始化+超类的初始化(绝大多数)
一个类的构造函数被重写,就要调用超类构造方法,否则会错误初始化
super在新式类中使用
代码块前加:
__metaclass__ = type
重写基类构造函数时:
super(derived_class,self).__init__()
即使类已继承多个超类,只需用1次super函数
python2.7中的super方法
30 eval()
返回字符串表达式的值
str = ‘[1,2,3]’
s = eval(str)
# Output: [1,2,3]
31 内核态 & 用户态
操作系统的两种CPU状态
-
内核态:运行,操作系统,程序
运行在R0特权级
进程能访问:所有的内存空间和对象,处理器不可被抢占 -
用户态:运行,用户,程序
运行在R3级(最低)特权级以上
进程能访问:有限的内存空间和对象,处理器可被抢占 -
内核态—>用户态:
设置程序状态字PSW -
用户态—>内核态:
系统调用,异常,外围设备的中断,陷入机制(访管指令)
32 各种锁
全局解释器锁(GIL)
gloal interpreter lock 保证线程安全
python解释器中的bool值,受互斥保护。
1CPU,同时,运行1线程
多线程,存在资源竞争,GIL保证线程唯一使用共享资源(cpu)
优点:
(1)避免加锁、解锁
(2)数据安全,多线程数据完整、状态同步
缺点:多核退化成单核,只能并发,不能并行
- io密集型任务:用多线程(资源调度)
- cpu密集型任务:用不着多线程,反而可能资源争夺,变慢
用多进程(资源分配),协程
同步锁
线程运行过程,出现i/o操作,cpu可能切换到别的线程,影响程序完整执行
在公共数据前后加:上锁、释放锁操作
保证,解释器级别下,程序唯一使用共享资源
递归锁
同一线程,多次请求,同一资源
RLock:可重入锁(Lock+Counter)
Counter记录请求次数,直到所有acquire被释放,其他线程才能获得资源
分为:可递归,非递归
乐观锁 & 悲观锁
-
乐观锁:
假设不会发生,并发冲突
只在提交操作时,检查是否违反数据完整性 -
悲观锁:
假设一定会发生,并发冲突
屏蔽一切可能违反数据完整性的操作
死锁
- 现象:2个及以上,进程/线程,执行过程,争夺资源,相互等待
- 原因:进程资源竞争,资源分配不当,推进顺序不当
- 产生条件:互斥,请求和保持,不剥夺,环路
- 避免方法:银行家算法
- 预防方法:摒弃产生条件的(2)-(4)
- 检测方法:资源分配图
- 解除方法:剥夺资源,撤销进程
python加锁方式
互斥锁,可重入锁,迭代死锁,互相调用死锁,自旋锁
33 python运行过程
解释型脚本语言
运行过程如下:
(1)虚拟机,读入py文件
(2)词法分析,编译成opcode(虚拟机认识的代码)
(3)虚拟机,解释opcode
最后一步非常慢,需要先将opcode编译成中间代码,再翻译成CPU可理解的指令
34 魔法
__slots__魔法,可以将内存占用率减少40%~50%
45 collections
(1)collections.defaultdict(int)
不需要检查是否有key存在
(2)collections.Counter(var)
以key,val的方式输出每个var出现的次数
(3)collections.deque()
创建双端队列
右边(队尾)添:d.append() ; d.extend()
右边(对尾)删:d.pop()
左边(队首)添:d.appendleft(); d.extendleft()
左边(队首)删:d.popleft()
限制队列大小:d= deque(maxlen=30)
(4)collections.namedtuple
46 异常
try:
可能异常的语句
except:
处理异常的代码
47 跳出双重循环
else在循环正常结束时执行
如果内层循环,是由于break中断,则跳过else语句,执行break
找2~9之间的质数:
48 检查对象的内存占用情况
sys.getsizeof(object)
import sys
mylist = range(0, 10000)
print(sys.getsizeof(mylist))
# 48
range函数返回的是一个类对象,它表现为一个列表,因此使用range函数比使用实际的包含一万个数字的列表要更加节省内存。
参考
https://github.com/taizilongxu/interview_python
https://www.cnblogs.com/gizing/p/10925286.html
https://blog.csdn.net/chinesehuazhou2/article/details/90746215
https://www.jiqizhixin.com/articles/2020-02-06?from=synced&keyword=%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E6%8A%80%E5%B7%A7