python函數把可變數據類型當默認參數值的問題(轉)

add by zhj: 文章寫的很好,其實只要默認參數在函數中只讀不寫,那默認值就不會被修改,可變類型作默認參數就不會有問題app

方法二中,當result is None時,修改result的指向,再也不指向默認參數對象,而是賦值一個新的對象。以下,能夠看到,result的id變化了函數

In [4]: def f(p=None, q=[]):
   ...:     print id(p), id(q)
   ...:     if p is None:
   ...:         p = []
   ...:         print id(p)
   ...:         

In [5]: f()
9568656 140309648126608
140309648094632

In [6]: f()
9568656 140309648126608
140309648074944

 

 

原文:https://blog.csdn.net/sinat_38068807/article/details/85677419測試

說明:默認參數值在函數被定義時已經計算出來,而不是在程序運行時。Python 程spa

序員常常犯的一個錯誤是把可變的數據類型(例如列表或者字典)看成默認參數值.net

(一)出現的問題

在下面的例子中,函數 buggy() 在每次調用時,添加參數 arg 到一個空的列表 result ,然
後打印輸出一個單值列表。可是存在一個問題:只有在第一次調用時列表是空的,第二次
調用時就會存在以前調用的返回值code

def buggy(arg, result=[]):
    result.append(arg)
    print(result)

print('--------1--------')
buggy('a')
print('--------2--------')
buggy('b')  # 指望獲得 ['b']

執行結果:對象

--------1--------
['a']
--------2--------
['a', 'b']

(二)解釋並測試

1.默認參數值在函數被定義時已經計算出來,而不是在程序運行時blog

2.只要函數調用時沒有傳遞新的列表來覆蓋默認參數列表,函數就會使用定義時的那個列表,而且操做依次疊加get

3.上面兩次調用中,都沒有傳遞新的列表,程序會調用定義函數時保存的默認參數,並在上一次的基礎上進行操做疊加,即:列表在append的時候會在 result原來的基礎上append追加值,因此會產生以上結果.class

咱們經過打印列表的ID進行辨識來看看:

def buggy(arg, result=[]):
    print(id(result))
    result.append(arg)
    print(result)

print('--------1--------')
buggy('a')
print('--------2--------')
buggy('b')  # expect ['b']

結果:

--------1--------
12205768
['a']
--------2--------
12205768
['a', 'b']

咱們會發現ID值是相同的;

說明兩次執行時使用的都是開始定義函數時的默認參數 ,進行了操做疊加

4.下面咱們傳遞新的列表看看:

def buggy(arg, result=[]):
    print(id(result))
    result.append(arg)
    print(result)

print('--------1--------')
buggy('a')
print('--------2--------')
buggy('b', [])  # 傳遞了新的列表

結果:

--------1--------
18497224
['a']
--------2--------
18504648
['b']

發現,列表id不一樣,而且獲得了咱們指望的值

(三)解決方法

方法1

# 若是寫成下面的樣子就會解決剛纔的問題:

def works(arg):
    result = []
    result.append(arg)
    print(result)

works('a')
works('b')

結果:

['a']
['b']

方法2:

# 這樣的修改也爲了代表是第一次調用跳過一些操做:

def nonbuggy(arg, result=None):
    if result is None:
        result = []
    result.append(arg)
    print(result)

nonbuggy('a')
nonbuggy('b')

結果:

['a']
['b']
相關文章
相關標籤/搜索