一、不要使用可變對(duì)象作為函數(shù)默認(rèn)值
代碼如下:In [1]: def append_to_list(value, def_list=[]):
...: def_list.append(value)
...: return def_list
...:
In [2]: my_list = append_to_list(1)
In [3]: my_list
Out[3]: [1]
In [4]: my_other_list = append_to_list(2)
In [5]: my_other_list
Out[5]: [1, 2] # 看到了吧,其實(shí)我們本來只想生成[2] 但是卻把第一次運(yùn)行的效果頁帶了進(jìn)來
In [6]: import time
In [7]: def report_arg(my_default=time.time()):
...: print(my_default)
...:
In [8]: report_arg() # 第一次執(zhí)行
1399562371.32
In [9]: time.sleep(2) # 隔了2秒
In [10]: report_arg()
1399562371.32 # 時(shí)間竟然沒有變
這2個(gè)例子說明了什么? 字典,集合,列表等等對(duì)象是不適合作為函數(shù)默認(rèn)值的. 因?yàn)檫@個(gè)默認(rèn)值實(shí)在函數(shù)建立的時(shí)候就生成了, 每次調(diào)用都是用了這個(gè)對(duì)象的”緩存”. 我在上段時(shí)間的分享python高級(jí)編程也說到了這個(gè)問題,這個(gè)是實(shí)際開發(fā)遇到的問題,好好檢查你學(xué)過的代碼, 也許只是問題沒有暴露
可以這樣改:
代碼如下:
def append_to_list(element, to=None):
if to is None:
to = []
to.append(element)
return to
二、生成器不保留迭代過后的結(jié)果
代碼如下:In [12]: gen = (i for i in range(5))
In [13]: 2 in gen
Out[13]: True
In [14]: 3 in gen
Out[14]: True
In [15]: 1 in gen
Out[15]: False # 1為什么不在gen里面了? 因?yàn)檎{(diào)用1->2,這個(gè)時(shí)候1已經(jīng)不在迭代器里面了,被按需生成過了
In [20]: gen = (i for i in range(5))
In [21]: a_list = list(gen) # 可以轉(zhuǎn)化成列表,當(dāng)然a_tuple = tuple(gen) 也可以
In [22]: 2 in a_list
Out[22]: True
In [23]: 3 in a_list
Out[23]: True
In [24]: 1 in a_list # 就算循環(huán)過,值還在
Out[24]: True
三、lambda在閉包中會(huì)保存局部變量
代碼如下:
In [29]: my_list = [lambda: i for i in range(5)]
In [30]: for l in my_list:
....: print(l())
....:
4
4
4
4
4
這個(gè)問題還是上面說的python高級(jí)編程中說過具體原因. 其實(shí)就是當(dāng)我賦值給my_list的時(shí)候,lambda表達(dá)式就執(zhí)行了i會(huì)循環(huán),直到 i =4,i會(huì)保留
但是可以用生成器
代碼如下:
In [31]: my_gen = (lambda: n for n in range(5))
In [32]: for l in my_gen:
....: print(l())
....:
0
1
2
3
4
也可以堅(jiān)持用list:
代碼如下:
In [33]: my_list = [lambda x=i: x for i in range(5)] # 看我給每個(gè)lambda表達(dá)式賦了默認(rèn)值
新聞熱點(diǎn)
疑難解答
圖片精選