python 默認參數問題

**

一個函數參數的默認值,僅僅在該函數定義的時候,被賦值一次

**

首先來看問題:

>>> 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)
所以,定義默認參數要牢記一點:默認參數必須指向不變對象!

可變對象與不可變對象

發佈了250 篇原創文章 · 獲贊 230 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章