為什麼這篇python def意思鄉民發文收入到精華區:因為在python def意思這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者KSJ (阿真)看板Python標題[心得] 關於 function (def) 的 defau...
--前言
這文章標題不知道下的好不好
我也沒爬文 如果已有類似觀念 麻煩推文說一下
本來還想把python原文書賣掉
發生這件人為bug後 還是留起來吧XD
--內容
這是個關於定義函式時 給定預設值 與 mutable object 的概念
為了簡化實際的案件 下面是一個例子
def show_append(x=[],y=2):
x.append(y)
print x
寫成這樣...
本來的意思是希望 show_append函式裡的二個變數
x 是個有 append method 的 object
y是被 append 的值
如果都沒給值的話 就來個範例 空的list 與 被加入的數2
但很多事情總是不如想像...
下面來三個範例
>>> show_append()
[2]
>>> show_append()
[2, 2]
>>> show_append()
[2, 2, 2]
這...這飯粒...有毒
跟預想的不一樣
原因是:
在定義函式中 預設的變數(x跟y) 是在定義函式執行時所產生(不是在呼叫的時候)
所以 x (也就是[])是在定義show_append函式時
就一直存在的東西
而因為[] 是mutable obj
在使用 append 這個in-place change的方法時
本身就會改變
所以 要範例的話 可以如下
>>> show_append([])
[2]
給個新的"[]" 就行了
順帶一提
>>> show_append()
[2, 2, 2, 2, 2]
原來的預設值還在喲~
順帶再提
也許你可能會這樣想
如果給x一個新的值[]行不行 像下面
>>> show_append(x=[])
[2]
x的預設直就變成空的[]了~??
當然是不行...
否則假使你用 show_append (y=3)
以後不就都append 3了?(又違反意思了)
在定義函式裡 使用的預設值 比方 def func(name = value_d): ...
呼叫func(name = value)
並不是創建name,並給一個新的值value
所以你不能在呼叫show_append時創建新的變數
像 show_append(another_value = 99)
呼叫時用的name 只是拿來對應func裡的name用而已 (找名字)
預設的value_d值仍然存在
所以
>>> show_append()
[2, 2, 2, 2, 2, 2]
一個也沒少喲~
--結論
要注意給函式的預設值是否為mutable,是否符合創造函式的原意
記住python這樣的特性 運用在該用的地方吧!!
記得 力量越大 bug也越大... 共de之
--題外話
總覺得不會碰上的事 總是會碰上...orz
當這樣的問題發生在class裡頭的__init__時候 就更難發現了(我這是這種)
希望不要跟我犯一樣的錯...(還是只有我...
以上 歡迎指正與分享
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.63.202
是指說 在runtime才"執行"產生函式嗎@@?
說來殘愧... 我在c與c++寫函式的時候還沒用過default值...
在我初學oop觀念時碰到的是python而非c++
c++的 private public的觀念 或是宣告class的方式
相較於python都較令我難理解
例如c++ . -> 在python下都是 . 理解能力的需求就不一樣
不過當然在c++的程式碼上 可讀性也許不夠 但理解後觀念會更清楚吧
我覺得還是該弄懂c++的類別觀念與寫法 (也許先略懂指標吧...
很多python相關的套件 說明文件還是在c++下較完整 例如PyQt
要了解而使用 以免像我對python def的誤用
其實我還蠻常用把cls instance當做變數在函式(別的class裡的)內傳來傳去
大部份是讀取需要的資料
修改資料的話就直接用method了 (classinstance.method("資料"))
我覺得在函式中修改instance時用instance的method 感覺還ok說
所以我覺得創造修改外部物件的函式應該是需要的
不知道這觀念對不對...
而我是以為class def __init__(self, arg = another_instance_create) 時
會重新創造 default arg裡的東西
所以中招了XD (如1F的文件的 important部份)
我參考的原文書裡有提了許多 3與2不同的地方
print, string type, type & class, range 等等
不知道function的修改呢~
有空再來看看:)
(這讓我想到 剛學python就抓3下來因為print變成func而無法helloworld的一段往事)
不過我目前使用的相關套件在2下仍有比較好的支援度
所以3還可以再緩一下吧
(我目前是用python2.5較多)