Note
注意点
-
for x in iterable- 如果
in后面==创建了新实例==可理解为==只被评估最初一次==,x就遍历最初一次创建的新实例,不会随s的变化而改变 ---for x in s[:]: - 而如果
in后面就是==没创建新实例==,则会被==反复评估==,x遍历的就是s,会随s变化而变化 ---for x in s:- 如果采用这种遍历方式要格外小心分析,如果只是extend还好,如果还有remove的话是会影响遍历的,比如我先遍历了第一个,但是第一个在过程中被删了,第二个成了第一个,这样我将不会再遍历新的第一个,即第二个无法被遍历到
- 但是对于
while循环来讲,无论如何它都是会被反复评估的 - 可见 example里的forin
- 如果
-
and和or都从左往右执行,遵循短路机制and执行到False时短路并返回False-
or执行到 非False时短路并返回 非False的值 -
and如果全为True,则返回最后一个的值 or如果全为False,则返回False
-
list的切片
- 将切片赋值给变量(单独的切片实例) --- 先创建一个切片长度的新list实例,将原list相应位置的元素依次赋值过去(可变浅拷贝、不可变深拷贝)
- 将变量(list)赋值给切片 --- 先将原list切片范围去除,并创建与变量同长度的元素框,再用变量依次赋值过去(可变浅拷贝、不可变深拷贝)
-
函数参数定义法
- 关键字(+默认参数)
*args接任意数量的位置参数**kwargs接受任意数量的关键字参数- 在函数定义中使用
*,表示后面的参数只能用关键字方式传入 - 在函数定义中使用
/,表示前面的参数只能用位置传递
-
函数参数传递法
- 位置参数与关键字传参混用时注意 --- ✅ 规则:位置参数要在关键字参数前面
*args函数参数表示法:f(1, 2, 3)等效于f(*[1, 2, 3]) or f(*(1,2,3))对list或tuple解包- 使用
**kwargs对字典进行解包传参 *args与**kwargs同时使用前者在前,后者在后
-
Python中一般函数的调用过程
- 在当前环境评估参数的值
- 函数创建新Frame,将值与symbol依次绑定
- 执行历程返回最终值
-
分析定义和调用被装饰器修饰的函数的情形
- 定义
- 装饰器函数的历程会在==被修饰函数定义时==执行
- 一直执行装饰器函数的例程,直到执行完 直接调用被修饰函数的装饰器
- 调用
- 执行 ==直接调用被修饰函数装饰器==的返回函数
- 定义
-
在python中的作用域不是像C里面那样由框决定,而是由Frame决定,在某个Frame定义的Symbol都会被绑定到该Frame上
- Symbol的lookup策略是
- 先在本Frame中查看、然后再在父Frame查看
- 另外,Python的作用域采用 Lexical Scope,也就是 由定义过程决定 Frame层级
- Python 调用函数时,会创建新的Frame,一个函数的父Frame由它在哪里定义决定
- 调用自定义函数时才会创建 Frame,Builtins的方法是不创建Frame的
- Symbol的lookup策略是
-
python的特殊字符串
f‘It is {word}.’使用word变量替换{word}'It is {0}'.format(word)使用word变量替换{0}
-
调用自定义函数时才会创建 Frame,Builtins的方法是不创建Frame的
-
float('inf')会返回一个用浮点数表示的正无穷值,可以与其他数值进行比较。 -
isinstance(obj,type)和type(obj) == type- 前者考虑继承关系,即obj即使不是type但是是type的子类实例也True
- 后者不考虑继承关系
-
当子类绑定方法中需要调用基类的绑定方法时,我们需要使用
super().method(args)- 不能使用 基类类名,因为是绑定方法,如果用类名我们需要创建一个基类的实例作为第一个参数,但是这样操作的就是基类的实例,而非本实例
super()方法不是创建一个新的基类实例而是寻找基类方法并将本实例作为self传过去运行基类的例程,因此操作的是本实例
-
python中对于可迭代对象都具有解包功能
- list、tuple、range、dict
a,b,c = list\tuple\range\dict- 注意,解包的变量数和可迭代对象项数要一致
- dict 直接解包是对 key 解包,而相对 value 解包可以
a,b,c = dict.values()
小窍门
-
遍历list中所有子串组合 --- 位运算
- 这个是为了返回和为偶数的子序列的list的函数,当然也可以通过互递归实现 见example里的even_set
def even_sublist(s): """返回s中和为偶数的子序列的list""" if not s: return None result = [] n = len(s) for i in range(1 << n): sublist = [s[j] for j in range(n) if (i & (1 << j))] if sum(sublist) % 2 == 0 and len(sublist) >= 1: result.append(sublist) return result
- 这个是为了返回和为偶数的子序列的list的函数,当然也可以通过互递归实现 见example里的even_set
-
递归抽象思想
- 在 涉及链表、Tree 和 图的问题中,经常会使用递归
- 在编写递归函数时,我们一定要有抽象思维,明白递归函数是什么作用,把它当成一个效用来看,不要一开始就分析复杂的递归过程,也就是说 将递归函数视作一般流,把递归调用视作效用
- 实在有问题了再分析,而且也是先分析抽象层面