**
一個函數參數的默認值,僅僅在該函數定義的時候,被賦值一次
**
首先來看問題:
>>> def add_end(L=[]):
... L.append('END')
... return L
...
>>>
>>> t=add_end()
>>>
>>> t
['END']
>>> t=add_end()
>>> t
['END', 'END']
>>> t=add_end([1])
>>> t
[1, 'END']
>>> t=add_end()
>>> t
['END', 'END', 'END']
>>> t=add_end([1])
>>> t
[1, 'END']
>>> t=add_end()
>>> t
['END', 'END', 'END', 'END']
Python函數在定義的時候(只在那個時刻賦值,此後調用不再賦值),默認參數L的值就被計算出來了,即[],因爲默認參數L也是一個變量,它指向對象[],每次調用該函數,如果改變了L的內容,則下次調用時,默認參數的內容就變了,不再是函數定義時的[]了
Python函數參數對於可變對象,函數內對參數的改變會影響到原始對象;對於不可變對象,函數內對參數的改變不會影響到原始參數。原因在於:
1、可變對象,參數改變的是可變對象,其內容可以被修改。
2、不可變對象,改變的是函數內變量的指向對象。
更明顯的例子:可以看出初始化時機
import datetime as dt
def log_time(message, time=dt.datetime.now()):
print("{0}: {1}".format(time.isoformat(), message))
每次我們調用log_time()時都期望它能夠正確提供當前時間。悲劇的是並沒有成功:默認參數在定義時求值(比如說當你首次導入模塊時),調用的結果如下
>>> log_time("message 1")
2015-02-10T21:20:32.998647: message 1
>>> log_time("message 2")
2015-02-10T21:20:32.998647: message 2
>>> log_time("message 3")
2015-02-10T21:20:32.998647: message 3
對於不可變對象,他的內內容發生改變時,變量的對象引用是不會變化的,所以上面的L一直是同一個地址的L,所以會不斷的家END 而當改成如下形式:
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
現在,無論調用多少次,都不會有問題。
None 是不可變對象,每次一賦值爲[]時,他指向的引用就會發生改變,輸出的結果也是改變後的引用內容,但再一次調用L還是之前的引用(None)
所以,定義默認參數要牢記一點:默認參數必須指向不變對象!