python 預設引數問題的陷阱

2022-10-04 22:03:34 字數 2588 閱讀 2506

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 ...