python 裡面乙個常見的陷阱就是函式的預設引數問題。如下:
def func(mylist = ):
mylist.append(1)
return mylist
以下的執行結果如下:
print func()
print func()
print func()
print func(['a'])
print func()
結果如下:
[1][1, 1]
[1, 1, 1]
['a', 1]
[1, 1, 1, 1]
如此結果, 前面三個可以看出 如果沒有指定引數的話, 每次呼叫函式時候, 呼叫的mylist 是同乙個物件。這是因為函式的預設引數,是在**編譯成pycodeobject的時候, 就已經建立了物件指標,並且存在該函式的func_default內。 以後在**執行,呼叫函式的時候,如果沒有指定引數的話, 每次呼叫的話, 該引數變數都是**編譯階段的變數指標所指定的物件。
www.cppcns.comprint func.func_default
此時結果就是:
([1, 1, 1, 1], )
預設引數分為兩種情況:
預設引數值是不可變物件
此時函式的 func_default 一直指向該不變物件, 如果函式內部修改了該變數, 那麼該預設引數會指向乙個新的不可變物件.
不過func_default 不變。 而每次呼叫函式都是讀取func_default, 因此每次執行都一樣。
in [30]: def func2(var = 1):
....: var += 1
....: return var
....:
in [31]: func2()
out[31]: 2
in [32]: func2()
out[32]: 2
in [34]: func2.func_defaults
out[34]: (1,)
預設引數是可變物件,比如 list, dict, class等
這種情況下,如果在函式內修改了指標所指的物件(並未建立新的物件), 那麼 func_default 就會改變。這正是開始的mylist發生變化的原因。看下面的例子,:
in [35]: def func(mylist = ):
....: mylist = #這裡 建立了新的物件,
mylist.append(1)
return mylist
in [44]: func()
out[44]: [1]
in [45]: func.func_defaults
out[45]: (,)
由於建立了物件, mylist 只是作為乙個 新建物件的別名存在, 後面在修改已經與 func_default 無關了。
預設引數的乙個應用
先看下面的乙個經典的例子:
def outer():
res =
for i in range(4):
def inner(j):
return j * i
res.append(inner)
return res
print [m(2) for m in outer()]
#簡略版本:
def multipliers():
return [lambda x : i * x for i in range(4)]
print [m(2) for m in multipliers()]
結果是 [6, 6, 6, 程式設計客棧6] , 而不是 [0, 2, 4, 6], 原因就是閉包的延程式設計客棧遲繫結。另外函式繫結的是變數而不是繫結數值。當迴圈結束了,i的值已經是3, 此時結果都是6. 乙個解決方法便是,使用預設引數繫結數值。如下改動:
def outer():
res =
for i in range(4):
def inner(j, i = i):
return j * i
res.append(inner)
jrgnvreturn res
print [m(2) for m in outer()]
#簡略版本:
def multipliers():
return [lambda x, i = i : i * x for i in range(4)]
print [m(2) for m in multipliers()]
這樣的話, 利用預設引數在**編譯的時候,便把引數寫到函式的func_default中, 就可以繫結0,1,2,3了。結果自然就是
[0, 2, 4, 6]
這就是預設引數的乙個應用。
上述還有乙個生成器修改的方式
def multipliers():
return (lambda x, i = i : i * x for i in range(4)) #修改成生成器
print [m(2) for m in multipliers()]
本文標題: python 預設引數問題的陷阱
本文位址: /jiaoben/python/143827.html
Python預設引數陷阱問題
def fun a,l print l fun hhh fun mmmm fun xingkd python中的def語句在每次執行的時候都初始化乙個函式物件,這個函式物件就是我們要呼叫的函式,可以把它當成乙個一般的物件,只不過這個物件擁有乙個可執行的方法和部分屬性,對於引數中提供了初始值的引數,由...
Python預設引數的陷阱
一 內建函式1.返回的是字典,字典裡面的鍵值對 全域性作用域的全部內容 print globals 2.返回的是字典,字典裡面的鍵值對 當前作用域的全部內容 print locals 二 預設引數的陷阱1.預設引數 沒傳值,可變資料型別在記憶體中是同乙個 def func name,alist re...
python 預設引數問題
首先來看問題 def add end l 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 ...