欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python函數(shù)的默認(rèn)參數(shù)設(shè)計示例詳解

 更新時間:2019年12月01日 08:18:04   作者:Mr-chen  
這篇文章主要給大家介紹了關(guān)于Python函數(shù)的默認(rèn)參數(shù)設(shè)計的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

在Python教程里,針對默認(rèn)參數(shù),給了一個“重要警告”的例子:

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

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

默認(rèn)值只會執(zhí)行一次,也沒說原因。會打印出結(jié)果:

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

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

準(zhǔn)備知識:指針

p指向不可變對象,比如數(shù)字。則相當(dāng)于p指針指向了不同的內(nèi)存地址。

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

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

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

根本原因

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

下面是一段從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. 在運行代碼時,運行到函數(shù)定義時,默認(rèn)參數(shù)的表達(dá)式就被執(zhí)行了。
  2. 函數(shù)調(diào)用時,不會再次運行默認(rèn)參數(shù)的表達(dá)式。⚠️ 這點和Ruby完全不同。
  3. 由此可知,如果默認(rèn)參數(shù),指向一個不變對象,例如L = 1。那么在函數(shù)調(diào)用時,在函數(shù)體內(nèi)對L重新賦值,L其實是一個新的指針, 指向的是一個新的內(nèi)存地址。而原來默認(rèn)參數(shù)L本身及指向的內(nèi)存地址,已經(jīng)儲存在最開始編譯時的函數(shù)定義中。可以用__default__查看。
  4. 如果默認(rèn)參數(shù)指向的是一個可變對象,如list, 那么L.append(a)是對可變對象自身的修改,L指向的內(nèi)存地址不變。所以每次調(diào)用函數(shù),默認(rèn)參數(shù)取出的都是這個內(nèi)存地址的對象。

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

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]))

#運行結(jié)果:
self 4353170064
1
self 4353170064
33
self 4353170064

默認(rèn)參數(shù)L,在編譯階段就綁定了,儲存在__default__內(nèi)。函數(shù)體內(nèi)的L = a表達(dá)式,生成的是新的變量。返回的L是新的變量,和默認(rèn)參數(shù)無關(guān)。

第四條,還是上面的例子, 改一下默認(rèn)參數(shù)的類型為可變對象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]))
#返回結(jié)果
self 4337586048
[1]
self 4337586048
[1, 33]
self 4337586048

由id號可知,返回的是默認(rèn)參數(shù)自身。

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

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

為什么Python要這么設(shè)計

 StackOverflow 上爭論很多。

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

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

有觀點認(rèn)為:

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

本文參考了:http://cenalulu.github.io/python/default-mutable-arguments/#toc1 ,并加入了自己的理解。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。

相關(guān)文章

  • PyQt實現(xiàn)異步數(shù)據(jù)庫請求的實戰(zhàn)記錄

    PyQt實現(xiàn)異步數(shù)據(jù)庫請求的實戰(zhàn)記錄

    開發(fā)軟件的時候不可避免要和數(shù)據(jù)庫發(fā)生交互,但是有些 SQL 請求非常耗時,如果在主線程中發(fā)送請求,可能會造成界面卡頓,本文將介紹一種讓數(shù)據(jù)庫請求變得和前端的 ajax 請求一樣簡單,希望對大家有所幫助
    2023-12-12
  • 在Python中使用AOP實現(xiàn)Redis緩存示例

    在Python中使用AOP實現(xiàn)Redis緩存示例

    本篇文章主要介紹了在Python中使用AOP實現(xiàn)Redis緩存示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • Python Selenium實現(xiàn)無可視化界面過程解析

    Python Selenium實現(xiàn)無可視化界面過程解析

    這篇文章主要介紹了Python Selenium實現(xiàn)無可視化界面過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • 關(guān)于Python中compile() 函數(shù)簡單實用示例詳解

    關(guān)于Python中compile() 函數(shù)簡單實用示例詳解

    這篇文章主要介紹了關(guān)于compile() 函數(shù)簡單實用示例,compile() 函數(shù)將一個字符串編譯為字節(jié)代碼,compile將代碼編譯為代碼對象,應(yīng)用在代碼中可以提高效率,本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • 如何使用Django默認(rèn)的Auth權(quán)限管理系統(tǒng)

    如何使用Django默認(rèn)的Auth權(quán)限管理系統(tǒng)

    本文主要介紹了如何使用Django默認(rèn)的Auth權(quán)限管理系統(tǒng),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 解讀Python編程中的命名空間與作用域

    解讀Python編程中的命名空間與作用域

    這篇文章主要介紹了Python編程中的命名空間與作用域,是Python入門學(xué)習(xí)中的重要知識,需要的朋友可以參考下
    2015-10-10
  • PyQt5利用QPainter繪制各種圖形的實例

    PyQt5利用QPainter繪制各種圖形的實例

    下面小編就為大家?guī)硪黄狿yQt5利用QPainter繪制各種圖形的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Opencv中cv2.cvtColor彩色圖轉(zhuǎn)灰度圖的其他6種方法

    Opencv中cv2.cvtColor彩色圖轉(zhuǎn)灰度圖的其他6種方法

    本文主要介紹了Opencv中cv2.cvtColor彩色圖轉(zhuǎn)灰度圖的其他6種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • python基礎(chǔ)之文件的備份以及定位

    python基礎(chǔ)之文件的備份以及定位

    這篇文章主要介紹了python文件的備份以及定位,實例分析了Python中返回一個返回值與多個返回值的方法,需要的朋友可以參考下
    2021-10-10
  • Pyhton中防止SQL注入的方法

    Pyhton中防止SQL注入的方法

    這篇文章主要介紹了Pyhton中防止SQL注入的方法,本文講解的方法簡單實用,需要的朋友可以參考下
    2015-02-02

最新評論