[地雷] 函數裡的預設參數,最好不要使用可變物件(mutable object) - tsungjung411/python-study GitHub Wiki
程式範例
def append_position(a, b, x_list = []):
for x in range(a, b + 1):
x_list.append(x)
# end-of-for
return x_list
# end-of-def
default_x_list = [1, 2]
x_list1 = append_position(3, 5, default_x_list)
print(x_list1) # [1, 2, 3, 4, 5]...預期結果
print(x_list1 == default_x_list) # True
x_list2 = append_position(1, 3)
print(x_list2) #[1, 2, 3]...預期結果
x_list3 = append_position(1, 5)
print(x_list3) # [1, 2, 3, 1, 2, 3, 4, 5]...非預期結果
print(x_list3 == x_list2) # True
執行結果:
[1, 2, 3, 4, 5]
True
[1, 2, 3]
[1, 2, 3, 1, 2, 3, 4, 5]
True
結果說明:
- 預設參數
x_list = []
執行參數初始化後,就不再執行第二次,因此後續的操作都是拿到同一個物件
- 只要預設參數是「可變物件(mutable object)」,都會有此情形,使用上要特別小心
- 同理,類別的成員也盡量不要使用「可變物件」,遇到的問題如同上面。每個產生出來物件,都拿到同樣類別的成員物件
正確寫法:
def append_position(a, b, x_list = None):
if x_list == None:
x_list = []
# end-of-if
for x in range(a, b + 1):
x_list.append(x)
# end-of-for
return x_list
# end-of-def
其他參考
關鍵字:
- 地雷, 陷阱, 臭蟲(bug),
- 方法(method), 函數(function), 宣告
- 默認參數/預設參數(default parameter), 無引數(no argument)
- 可變物件/可變動物件(mutable object), 不可變物件/不可變動物件(immutable object)