成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Python中的默認(rèn)參數(shù)值

開發(fā) 后端 前端
不要使用可變對象作為函數(shù)的默認(rèn)參數(shù)例如 list,dict,因?yàn)閐ef是一個(gè)可執(zhí)行語句,只有def執(zhí)行的時(shí)候才會(huì)計(jì)算默認(rèn)默認(rèn)參數(shù)的值,所以使用默認(rèn)參數(shù)會(huì)造成函數(shù)執(zhí)行的時(shí)候一直在使用同一個(gè)對象,引起bug。

文章的主題

不要使用可變對象作為函數(shù)的默認(rèn)參數(shù)例如 list,dict,因?yàn)?code>def是一個(gè)可執(zhí)行語句,只有def執(zhí)行的時(shí)候才會(huì)計(jì)算默認(rèn)默認(rèn)參數(shù)的值,所以使用默認(rèn)參數(shù)會(huì)造成函數(shù)執(zhí)行的時(shí)候一直在使用同一個(gè)對象,引起bug。

基本原理

在 Python 源碼中,我們使用def來定義函數(shù)或者方法。在其他語言中,類似的東西往往只是一一個(gè)語法聲明關(guān)鍵字,但def卻是一個(gè)可執(zhí)行的指令。Python代碼執(zhí)行的時(shí)候先會(huì)使用 compile 將其編譯成 PyCodeObject.

PyCodeObject 本質(zhì)上依然是一種靜態(tài)源代碼,只不過以字節(jié)碼方式存儲(chǔ),因?yàn)樗嫦蛱摂M機(jī)。因此 Code 關(guān)注的是如何執(zhí)行這些字節(jié)碼,比如棧空間大小,各種常量變量符號列表,以及字節(jié)碼與源碼行號的對應(yīng)關(guān)系等等。

PyFunctionObject 是運(yùn)行期產(chǎn)生的。它提供一個(gè)動(dòng)態(tài)環(huán)境,讓 PyCodeObject 與運(yùn)行環(huán)境關(guān)聯(lián)起來。同時(shí)為函數(shù)調(diào)用提供一系列的上下文屬性,諸如所在模塊、全局名字空間、參數(shù)默認(rèn)值等等。這是def語句執(zhí)行的時(shí)候干的活。

PyFunctionObject 讓函數(shù)面向邏輯,而不僅僅是虛擬機(jī)。PyFunctionObject 和 PyCodeObject 組合起來才是一個(gè)完整的函數(shù)。

下文翻譯了一篇文章,有一些很好的例子。但是由于水平有限,有些不會(huì)翻譯或者有些翻譯有誤,敬請諒解。如果有任何問題請發(fā)郵件到 acmerfight圈gmail.com,感激不盡

主要參考資料 書籍:《深入Python編程》 大牛:shell 和 Topsky

原文鏈接

Python對于函數(shù)中默認(rèn)參數(shù)的處理往往會(huì)給新手造成困擾(但是通常只有一次)。

當(dāng)你使用“可變”的對象作為函數(shù)中作為默認(rèn)參數(shù)時(shí)會(huì)往往引起問題。因?yàn)樵谶@種情況下參數(shù)可以在不創(chuàng)建新對象的情況下進(jìn)行修改,例如 list dict。

  1. >>> def function(data=[]):  
  2. ...     data.append(1)  
  3. ...     return data  
  4. ...  
  5. >>> function()  
  6. [1]  
  7. >>> function()  
  8. [11]  
  9. >>> function()  
  10. [111]  

像你所看到的那樣,list變得越來越長。如果你仔細(xì)地查看這個(gè)list。你會(huì)發(fā)現(xiàn)list一直是同一個(gè)對象。

  1. >>> id(function())  
  2. 12516768 
  3. >>> id(function())  
  4. 12516768 
  5. >>> id(function())  
  6. 12516768 

原因很簡單: 在每次函數(shù)調(diào)用的時(shí)候,函數(shù)一直再使用同一個(gè)list對象。這么使用引起的變化,非常“sticky”。

為什么會(huì)發(fā)生這種情況?

當(dāng)且僅當(dāng)默認(rèn)參數(shù)所在的“def”語句執(zhí)行的時(shí)候,默認(rèn)參數(shù)才會(huì)進(jìn)行計(jì)算。請看文檔描述

http://docs.python.org/ref/function.html

的相關(guān)部分。

"def"是Python中的可執(zhí)行語句,默認(rèn)參數(shù)在"def"的語句環(huán)境里被計(jì)算。如果你執(zhí)行了"def"語句多次,每次它都將會(huì)創(chuàng)建一個(gè)新的函數(shù)對象。接下來我們將看到例子。

用什么來代替?

像其他人所提到的那樣,用一個(gè)占位符來替代可以修改的默認(rèn)值。None

  1. def myfunc(value=None):  
  2.     if value is None:  
  3.         value = []  
  4.     # modify value here  

如果你想要處理任意類型的對象,可以使用sentinel

  1. sentinel = object()  
  2.  
  3. def myfunc(value=sentinel):  
  4.     if value is sentinel:  
  5.         value = expression  
  6.     # use/modify value here  

在比較老的代碼中,written before “object” was introduced,你有時(shí)會(huì)看到

  1. sentinel = ['placeholder']  
  2.  
  3. 譯者注:太水,真的不知道怎么翻譯了。我說下我的理解 有時(shí)邏輯上可能需要傳遞一個(gè)None,而你的默認(rèn)值可能又不是None,而且還剛好是個(gè)列表,列表不  
  4. 可以寫在默認(rèn)值位置,所以你需要占位符,但是用None,你又不知道是不是調(diào)用者傳遞過來的那個(gè)  

正確地使用可變參數(shù)

最后需要注意的是一些高深的Python代碼經(jīng)常會(huì)利用這個(gè)機(jī)制的優(yōu)勢;舉個(gè)例子,如果在一個(gè)循環(huán)里創(chuàng)建一些UI上的按鈕,你可能會(huì)嘗試這樣去做:

  1. for i in range(10):  
  2.     def callback():  
  3.         print "clicked button", i  
  4.     UI.Button("button %s" % i, callback)  

但是你卻發(fā)現(xiàn)callback打印出相同的數(shù)字(在這個(gè)情況下很可能是9)。原因是Python的嵌套作用域只是綁定變量,而不是綁定數(shù)值的,所以callback只看到了變量i綁定的最后一個(gè)數(shù)值。為了避免這種情況,使用顯示綁定。

  1. for i in range(10):  
  2.     def callback(i=i):  
  3.         print "clicked button", i  
  4.     UI.Button("button %s" % i, callback)  

i=i把callback的參數(shù)i(一個(gè)局部變量)綁定到了當(dāng)前外部的i變量的數(shù)值上。(譯者注:如果不理解這個(gè)例子,請看http://stackoverflow.com/questions/233673/lexical-closures-in-python)

另外的兩個(gè)用途local caches/memoization

  1. def calculate(a, b, c, memo={}):  
  2.     try:  
  3.         value = memo[a, b, c] # return already calculated value  
  4.     except KeyError:  
  5.         value = heavy_calculation(a, b, c)  
  6.         memo[a, b, c] = value # update the memo dictionary  
  7.     return value  

(對一些遞歸算法非常好用)

對高度優(yōu)化的代碼而言, 會(huì)使用局部變量綁全局的變量:

  1. import math  
  2.  
  3. def this_one_must_be_fast(x, sin=math.sin, cos=math.cos):  
  4.     ...  

這是如何工作的?

當(dāng)Python執(zhí)行一條def語句時(shí), 它會(huì)使用已經(jīng)準(zhǔn)備好的東西(包括函數(shù)的代碼對象和函數(shù)的上下文屬性),創(chuàng)建了一個(gè)新的函數(shù)對象。同時(shí),計(jì)算了函數(shù)的默認(rèn)參數(shù)值。

不同的組件像函數(shù)對象的屬性一樣可以使用。上文用到的'function'

  1. >>> function.func_name  
  2. 'function' 
  3. >>> function.func_code  
  4. <code object function at 00BEC770, file "<stdin>", line 1>  
  5. >>> function.func_defaults  
  6. ([111],)  
  7. >>> function.func_globals  
  8. {'function': <function function at 0x00BF1C30>,  
  9. '__builtins__': <module '__builtin__' (built-in)>,  
  10. '__name__''__main__''__doc__'None}  

這樣你可以訪問默認(rèn)參數(shù),你甚至可以修改它。

  1. >>> function.func_defaults[0][:] = []  
  2. >>> function()  
  3. [1]  
  4. >>> function.func_defaults  
  5. ([1],)  

然而我不推薦你平時(shí)這么使用。

另一個(gè)重置默認(rèn)參數(shù)的方法是重新執(zhí)行相同的def語句,Python將會(huì)和代碼對象創(chuàng)建一個(gè)新的函數(shù)對象,并計(jì)算默認(rèn)參數(shù),并且把新創(chuàng)建的函數(shù)對象賦值給了和上次相同的變量。但是再次強(qiáng)調(diào),只有你清晰地知道在做什么的情況下你才能這么做。

And yes, if you happen to have the pieces but not the function, you can use the function class in the new module to create your own function object.

原文鏈接:https://github.com/acmerfight/insight_python/blob/master/Default_Parameter.md#

責(zé)任編輯:林師授 來源: github.com
相關(guān)推薦

2021-02-05 07:33:05

JavaScript參數(shù)ES6

2024-07-26 08:53:09

前端參數(shù)后端

2012-02-02 15:36:21

Hibernate

2021-07-31 19:21:34

Python下劃線數(shù)值

2025-02-12 10:51:51

2010-03-12 16:07:10

Python默認(rèn)參數(shù)

2009-07-21 15:46:48

獲得output參數(shù)值iBATIS教程

2023-12-25 22:19:35

函數(shù)

2022-11-14 07:08:23

Python函數(shù)參數(shù)

2024-06-19 10:35:32

C++編程語言

2024-06-21 09:37:02

DefPython函數(shù)

2024-02-26 08:52:20

Python傳遞函數(shù)參數(shù)參數(shù)傳遞類型

2019-12-11 16:21:30

Python參數(shù)化測試框架

2024-06-21 09:02:27

.NET開發(fā)C#

2009-06-26 16:12:14

propertiesSpring

2021-10-04 14:56:09

機(jī)器學(xué)習(xí)函數(shù)參數(shù)

2024-01-23 11:21:24

2021-11-08 10:45:07

Python命令工具

2010-11-08 14:47:02

Powershell函數(shù)

2012-05-30 15:25:22

JDKURLConnectiJava
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 91欧美精品成人综合在线观看 | 亚洲综合无码一区二区 | 91精品国产一区二区在线观看 | 男人天堂网址 | 亚洲午夜av久久乱码 | 9久久婷婷国产综合精品性色 | 亚洲一区二区精品视频 | 亚洲视频中文 | 精品视频在线观看 | 精品在线观看一区二区 | 亚洲日韩欧美一区二区在线 | 婷婷综合网 | 亚洲一区二区三区四区五区中文 | 免费国产一区 | 手机av在线 | 亚洲成av人片在线观看 | 精品久久久久久红码专区 | 99在线观看视频 | 日本不卡一区二区三区在线观看 | 一区二区三区中文字幕 | 国产亚洲精品综合一区 | 国产一区二区视频在线 | 精品国产青草久久久久福利 | 亚洲精品视频在线观看视频 | 三级成人在线 | 日韩精品一区二区三区在线播放 | 国产福利在线小视频 | www.jizzjizz| 色小姐综合网 | 国产精品视频一区二区三区四区国 | 日本一区二区不卡 | 国产高清视频一区 | 精品国产乱码久久久久久老虎 | 免费观看黄色片视频 | 国产精品视频网 | 婷婷在线免费 | 久久精品欧美电影 | 久久久青草婷婷精品综合日韩 | 免费黄视频网站 | 国产精品人人做人人爽 | 久久国产精品精品国产色婷婷 |