一、不要使用可變對象作為函數默認值
代碼如下: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] # 看到了吧,其實我們本來只想生成[2] 但是卻把第一次運行的效果頁帶了進來
In [6]: import time
In [7]: def report_arg(my_default=time.time()):
...: print(my_default)
...:
In [8]: report_arg() # 第一次執行
1399562371.32
In [9]: time.sleep(2) # 隔了2秒
In [10]: report_arg()
1399562371.32 # 時間竟然沒有變
這2個例子說明了什么? 字典,集合,列表等等對象是不適合作為函數默認值的. 因為這個默認值實在函數建立的時候就生成了, 每次調用都是用了這個對象的”緩存”. 我在上段時間的分享python高級編程也說到了這個問題,這個是實際開發遇到的問題,好好檢查你學過的代碼, 也許只是問題沒有暴露
可以這樣改:
代碼如下:
def append_to_list(element, to=None):
if to is None:
to = []
to.append(element)
return to
二、生成器不保留迭代過后的結果
代碼如下: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里面了? 因為調用1->2,這個時候1已經不在迭代器里面了,被按需生成過了
In [20]: gen = (i for i in range(5))
In [21]: a_list = list(gen) # 可以轉化成列表,當然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 # 就算循環過,值還在
Out[24]: True
三、lambda在閉包中會保存局部變量
代碼如下:
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
這個問題還是上面說的python高級編程中說過具體原因. 其實就是當我賦值給my_list的時候,lambda表達式就執行了i會循環,直到 i =4,i會保留
但是可以用生成器
代碼如下:
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
也可以堅持用list:
代碼如下:
In [33]: my_list = [lambda x=i: x for i in range(5)] # 看我給每個lambda表達式賦了默認值
新聞熱點
疑難解答