python文档中关于默认参数是这样说的:
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call.
因此,如下代码:
def function(data=[]):
print id(data), data
data.append(1)
for i in range(3):
function()
输出结果为:
4462873272 []
4462873272 [1]
4462873272 [1, 1]
一切正像文档中说的那样,data只计算一次,之后的调用返回的是已经计算出来的值(因此,id(data)没有变化,每次append均针对同一个data)。
但是我们带参数调用function时,即:
for i in range(3):
function([])
输出结果为:
4462872984 []
4462872984 []
4462872984 []
data的值是符合预期的,但是三次调用function,id(data)的值竟然也一样,这个是为什么呢?带参数传递时,每次调用都应该是新建data的吧。
認真唸文件啊:https://docs.python.org/2/library/functions.html#id 。
Because:
CPython中id的實作概念上相當於物件在記憶體中的位址。那請看這段程式碼:
前後是兩個不同的list對象,但既然前面一個對像用完就被銷毀掉了,那後面的一個list就可能重用相同的內存空間,所以id返回的地址就是一樣的了。
LZ請注意常數與變數的區別, 你想要個不同的id, 得用list()。
前一陣子我也是剛學python, 看到關於預設參數列表的一部分, 說一下我的理解.
當呼叫函數f() 連續三次時,
第一次 f() 會找到預設參數 data = []
而且它在記憶體中的位址是能通過 類似 'f.data' 尋址的.
接下來再次呼叫 f() 會重複以上操作, 因為沒有輸入一個新的參數, 會預設還是找到先前的data作為此次參數列表.
f()
f()
另外 也可以呼叫 f.defaults 這個屬性來查看函數f當前情況的預設參數是什麼
如 定義完f後,
所以預設參數在前後幾次 f()執行過程中是可變的.
而如果呼叫f([]) 的話 是不會對預設參數產生影響的,
如果有興趣還可以試試看 對
f(data = [] ) 進行迭代 :)
可以參考這裡 覺得講的很清楚 Python 函數的參數
這個問題是這樣子的...
這是算是python比較高級的內容了吧..初學者基本上都會碰到這個問題
好了,正文開始
函數的內省導致了,你的參數是函數類型的一個屬性(雖然沒辦法用
.
來訪問).這也就是意味著,你在定義函數的時候,你的參數已經成了這個函數對象的一部分了..類似於:
你可以發現有剛剛的
"a"
被印出來了..函數這邊也是一樣的.定義的參數屬性是共享的
但是以上規則僅針對於可變資料型別,例如清單
因為不可變資料型別不是在目前這個記憶體區塊裡面修改的...而是指向了另外一個記憶體區塊..
延伸閱讀:
兩個python特性:
1. python的動態型別問題:
動態類型的意思是:你的變數只是一個類似指標的東西.只不過他可以隨便亂指...他指向的是一個型別.這個類型可以是整數,字串,類別等等.
你的一個變數可以更換指向的類型.例如:
a = 1
中a
指向的是一個整數類型.這個整數類型的值是1
(當然還有其他一些組成部分,例如還有count和類型聲明等等)但是當你從新指向的時候,比如:
a = "hello world"
,那麼發生的事情是,a
這個變數指向了一個字串類型,而之前1
這個整型發生的變化是count-1,等count為0了記憶體才被回收.這就是傳說中的動態型
2. 函數的內省
函數在python中也是型態.
例如你
那麼就是產生了一個函數型別,賦值給foo這個變數了..
而這個型別中所有東西都可以透過域運算子
.
來操作.同意ls