1. 可变的默认参数python
错误示例闭包
>>> def lala(l=[]): ... l.append(123) ... print l ... >>> lala() [123] >>> lala() [123, 123] >>> lala() [123, 123, 123]
缘由是,一个函数的默认值,仅在函数被定义时赋值一次。app
解决方法函数
>>> def lala(l=None): ... if l is None: ... l = [] ... l.append(123) ... print l ... >>> lala() [123] >>> lala() [123] >>> lala([456]) [456, 123]
2. 闭包问题spa
问题1:指望获得一个每执行一次,数字加1的函数code
错误示例对象
>>> def counter(): ... count = 0 ... def func(): ... count += 1 ... print count ... return func ... >>> lala = counter() >>> lala() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in func UnboundLocalError: local variable 'count' referenced before assignment
错误的缘由是,在python中,当试图为一个变量赋值时,会认为该变量在local(见《命名空间与做用域》)blog
正确的作法作用域
>>> def counter(): ... count = [0] ... def func(): ... count[0] += 1 ... print count[0] ... return func ... >>> lala = counter() >>> lala() 1 >>> lala() 2
由于在list是可变对象,所以能够巧妙的跳过这个限制。for循环
3. for 循环相关
1. 循环的同时修改列表
目的:传入一个纯数字的列表,将每一个数字的平方添加在原列表中
错误的作法:
>>> def lala(l): ... for i in l: ... l.append(i**2) ... >>> lala([1,2,3]) #死循环
正确作法: 用list[:]得到一个拷贝
>>> def lala(l): ... for i in l[:]: ... l.append(i**2) ... return l ... >>> lala([1,2,3]) [1, 2, 3, 1, 4, 9]
2. for循环不会引入新的命名空间
>>> for i in [1,2,3]: ... print i ... 1 2 3 >>> i 3
感受i应该是循环内部使用的一个变量,可是却发现循环结束后,它"泄漏"到外部了,这个没有解决办法,本身注意一下吧
3. for循环闭包问题
目的:指望获得5个函数,分别是将一个数字与0,1,2,3,4相乘
错误作法:
>>> def create(): ... return [lambda x: x * i for i in range(5)] ... >>> for i in create(): ... i(2) ... 8 8 8 8 8
这是后期绑定(late binding)致使的,这是指内层函数被执行时,才会去查找该变量的值。请注意上面讲的,for循环会致使变量泄漏,因此当函数执行的时候,i已经等于4了。
上面的代码等价于:
>>> def create(): ... result = [] ... for i in range(5): ... def lala(x): ... return x * i ... result.append(lala) ... return result
再理解一次,内层函数lala在执行时,才会去找i是多少,而执行的时候i已经等于4了。
解决方法:
>>> def create(): ... return [lambda x, y=i: x * y for i in range(5)] ... >>> for i in create(): ... i(2) ... 0 2 4 6 8
利用前面所讲的,带默认函数的函数将会在函数定义时完成赋值,来解决这个问题
未完成