91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Python中使用函數的默認參數

發布時間:2021-04-14 16:14:04 來源:億速云 閱讀:198 作者:Leah 欄目:開發技術

怎么在Python中使用函數的默認參數?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

在Python教程里,針對默認參數,給了一個“重要警告”的例子:

def f(a, L=[]):
  L.append(a)
  return L

print(f(1))
print(f(2))
print(f(3))

默認值只會執行一次,也沒說原因。會打印出結果:

[1]
[1, 2]
[1, 2, 3]

因為學的第一門語言是Ruby,所以感覺有些奇怪。 但肯定的是方法f一定儲存了變量L。

準備知識:指針

p指向不可變對象,比如數字。則相當于p指針指向了不同的內存地址。

p指向的是可變對象,比如list。list自身的改變,并不會改變list對象自身所在的內存地址。所以p指向的內存地址不變。

>>> p = 1
>>> id(p)
>>> p = p + 1
>>> id(p)
>>> p = 11
>>> id(p)

>>> p = []
>>> id(p)
>>> p.append(11)
>>> id(p)

根本原因

Python函數的參數默認值,是在編譯階段就綁定了。(寫代碼時就定義了。)

下面是一段從Python Common Gotchas中摘錄的原因解釋:

Python's default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

由此可知:

  1. 在運行代碼時,運行到函數定義時,默認參數的表達式就被執行了。

  2. 函數調用時,不會再次運行默認參數的表達式。?? 這點和Ruby完全不同。

  3. 由此可知,如果默認參數,指向一個不變對象,例如L = 1。那么在函數調用時,在函數體內對L重新賦值,L其實是一個新的指針, 指向的是一個新的內存地址。而原來默認參數L本身及指向的內存地址,已經儲存在最開始編譯時的函數定義中。可以用__default__查看。

  4. 如果默認參數指向的是一個可變對象,如list, 那么L.append(a)是對可變對象自身的修改,L指向的內存地址不變。所以每次調用函數,默認參數取出的都是這個內存地址的對象。

第三條,修改上面的例子:

def f(a, L = 1):
  L = a
  print(id(L))
  return L

print("self",id(f.__defaults__[0]))
print(f(1))
print("self",id(f.__defaults__[0]))
print(f(33))
print("self",id(f.__defaults__[0]))

#運行結果:
self 4353170064
1
self 4353170064
33
self 4353170064

默認參數L,在編譯階段就綁定了,儲存在__default__內。函數體內的L = a表達式,生成的是新的變量。返回的L是新的變量,和默認參數無關。

第四條,還是上面的例子, 改一下默認參數的類型為可變對象list:

def f(a, L = []):
  L.append(a)
  print(id(L))
  return L
# L = f(1)
print("self",id(f.__defaults__[0]))
print(f(1))
print("self",id(f.__defaults__[0]))
print(f(33))
print("self",id(f.__defaults__[0]))
#返回結果
self 4337586048
[1]
self 4337586048
[1, 33]
self 4337586048

由id號可知,返回的是默認參數自身。

如何避免這個陷阱帶來不必要麻煩

def f(a, L = None):
  if L is None:
    L = []
  L.append(a)
  return L

為什么Python要這么設計

 StackOverflow 上爭論很多。

Ruby之所以沒有這個問題,我想是因為Ruby的def關鍵字定義了一個封閉作用域,任何數據都必須通過參數傳入到方法內,才能用。

和Ruby比,Python參數的作用被大大消弱了。Python的出現晚于Ruby,其創始人肯定參考了Ruby的設計。拋棄了這個設計,選擇了類似javascript的函數方式。def定義的函數,執行時是可以接收外部作用域的變量的。

有觀點認為:

出于Python編譯器的實現方式考慮,函數是一個內部一級對象。而參數默認值是這個對象的屬性。在其他任何語言中,對象屬性都是在對象創建時做綁定的。因此,函數參數默認值在編譯時綁定也就不足為奇了。

關于怎么在Python中使用函數的默認參數問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

中山市| 夏河县| 武陟县| 合作市| 开江县| 沙雅县| 纳雍县| 陇西县| 炉霍县| 监利县| 长治市| 曲周县| 天等县| 维西| 长宁县| 安义县| 溧水县| 武山县| 城固县| 东乌珠穆沁旗| 永宁县| 太原市| 汝南县| 花莲县| 芮城县| 无为县| 绩溪县| 明溪县| 靖宇县| 大兴区| 元朗区| 湟中县| 东莞市| 将乐县| 麻阳| 新田县| 五莲县| 四子王旗| 新民市| 会理县| 塔河县|