国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PyTips 0x04 - Python 閉包與作用域

leejan97 / 2849人閱讀

摘要:項(xiàng)目地址閉包在計(jì)算機(jī)科學(xué)中,閉包英語,又稱詞法閉包或函數(shù)閉包,是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。

項(xiàng)目地址:https://git.io/pytips

閉包(Closure)

在計(jì)算機(jī)科學(xué)中,閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函數(shù)閉包(function closures),是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。
[維基百科::閉包(計(jì)算機(jī)科學(xué))]

0x02 Python 中的函數(shù)式編程 本來也應(yīng)該包括閉包的概念,但是我覺得閉包更重要的是對(duì)作用域(Scope)的理解,因此把它多帶帶列出來,同時(shí)可以理順一下 Python 的作用域規(guī)則。

閉包的概念最早出現(xiàn)在函數(shù)式編程語言中,后來被一些命令式編程語言所借鑒。尤其是在一些函數(shù)作為一等公民的語言中,例如JavaScript就經(jīng)常用到(在JavaScript中函數(shù)幾乎可以當(dāng)做“特等公民”看待),我之前也寫過一篇關(guān)于JavaScript閉包的文章(圖解Javascript上下文與作用域),實(shí)際上閉包并不是太復(fù)雜的概念,但是可以借助閉包更好地理解不同語言的作用域規(guī)則。

命名空間與作用域

0x00 The Zen of Python的最后一句重點(diǎn)強(qiáng)調(diào)命名空間的概念,我們可以把命名空間看做一個(gè)大型的字典類型(Dict),里面包含了所有變量的名字和值的映射關(guān)系。在 Python 中,作用域?qū)嶋H上可以看做是“在當(dāng)前上下文的位置,獲取命名空間變量的規(guī)則”。在 Python 代碼執(zhí)行的任意位置,都至少存在三層嵌套的作用域:

最內(nèi)層作用域,最早搜索,包含所有局部變量(Python 默認(rèn)所有變量聲明均為局部變量)

所有包含當(dāng)前上下文的外層函數(shù)的作用域,由內(nèi)而外依次搜索,這里包含的是非局部非全局的變量

一直向上搜索,直到當(dāng)前模塊的全局變量

最外層,最后搜索的,內(nèi)置(built-in)變量

在任意執(zhí)行位置,可以將作用域看成是對(duì)下面這樣一個(gè)命名空間的搜索:

scopes = {
    "local": {"locals": None,
             "non-local": {"locals": None,
                          "global": {"locals": None,
                                    "built-in": ["built-ins"]}}},
}

除了默認(rèn)的局部變量聲明方式,Python 還有globalnonlocal兩種類型的聲明(nonlocal是Python 3.x之后才有,2.7沒有),其中 global 指定的變量直接指向(3)當(dāng)前模塊的全局變量,而nonlocal則指向(2)最內(nèi)層之外,global以內(nèi)的變量。這里需要強(qiáng)調(diào)指向(references and assignments)的原因是,普通的局部變量對(duì)最內(nèi)層局部作用域之外只有只讀(read-only)的訪問權(quán)限,比如下面的例子:

x = 100
def main():
    x += 1
    print(x)
main()
---------------------------------------------------------------------------

UnboundLocalError                         Traceback (most recent call last)

 in ()
      3     x += 1
      4     print(x)
----> 5 main()


 in main()
      1 x = 100
      2 def main():
----> 3     x += 1
      4     print(x)
      5 main()
UnboundLocalError: local variable "x" referenced before assignment

這里拋出UnboundLocalError,是因?yàn)?b>main()函數(shù)內(nèi)部的作用域?qū)τ谌肿兞?b>x僅有只讀權(quán)限,想要在main()中對(duì)x進(jìn)行改變,不會(huì)影響全局變量,而是會(huì)創(chuàng)建一個(gè)新的局部變量,顯然無法對(duì)還未創(chuàng)建的局部變量直接使用x += 1。如果想要獲得全局變量的完全引用,則需要global聲明:

x = 100
def main():
    global x
    x += 1
    print(x)
    
main()
print(x) # 全局變量已被改變
101
101
Python 閉包

到這里基本上已經(jīng)了解了 Python 作用域的規(guī)則,那么我們來仿照 JavaScript 寫一個(gè)計(jì)數(shù)器的閉包:

"""
/* JavaScript Closure example */
var inc = function(){  
  var x = 0;
  return function(){
    console.log(x++);
  };
};
var inc1 = inc()
var inc2 = inc()
"""

# Python 3.5
def inc():
    x = 0
    def inner():
        nonlocal x
        x += 1
        print(x)
    return inner
inc1 = inc()
inc2 = inc()

inc1()
inc1()
inc1()
inc2()
1
2
3
1

對(duì)于還沒有nonlocal關(guān)鍵字的 Python 2.7,可以通過一點(diǎn)小技巧來規(guī)避局部作用域只讀的限制:

# Python 2.7
def inc():
    x = [0]
    def inner():
        x[0] += 1
        print(x[0])
    return inner
inc1 = inc()
inc2 = inc()

inc1()
inc1()
inc1()
inc2()
1
2
3
1

上面的例子中,inc1()是在全局環(huán)境下執(zhí)行的,雖然全局環(huán)境是不能向下獲取到inc()中的局部變量x的,但是我們返回了一個(gè)inc()內(nèi)部的函數(shù)inner(),而inner()對(duì)inc()中的局部變量是有訪問權(quán)限的。也就是說inner()inc()內(nèi)的局部作用域打包送給了inc1inc2,從而使它們各自獨(dú)立擁有了一塊封閉起來的作用域,不受全局變量或者任何其它運(yùn)行環(huán)境的影響,因此稱為閉包。

閉包函數(shù)都有一個(gè)__closure__屬性,其中包含了它所引用的上層作用域中的變量:

print(inc1.__closure__[0].cell_contents)
print(inc2.__closure__[0].cell_contents)
[3]
[1]
參考

9.2. Python Scopes and Namespaces

Visualize Python Execution

Wikipedia::Closure

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/37791.html

相關(guān)文章

  • PyTips 0x0c - Python 知之深淺

    摘要:不可變對(duì)象包括,,,,等,可變對(duì)象包括,,等。在中,賦值的過程僅僅是創(chuàng)建一個(gè)某個(gè)值的對(duì)象將變量名指向引用這個(gè)對(duì)象。這就像語言中指針的概念,只不過更靈活地是中的變量隨時(shí)可以指向其它對(duì)象不分類型,其它變量也可以指向這一對(duì)象。 項(xiàng)目地址:https://git.io/pytips Python 中的對(duì)象分為兩種:可變對(duì)象(mutable)和不可變對(duì)象(immutable)。不可變對(duì)象包括in...

    LoftySoul 評(píng)論0 收藏0
  • PyTips 0x0d - Python 上下文管理器

    摘要:項(xiàng)目地址引入了語句與上下文管理器類型,其主要作用包括保存重置各種全局狀態(tài),鎖住或解鎖資源,關(guān)閉打開的文件等。了解了語句的執(zhí)行過程,我們可以編寫自己的上下文管理器。生成器的寫法更簡(jiǎn)潔,適合快速生成一個(gè)簡(jiǎn)單的上下文管理器。 項(xiàng)目地址:https://git.io/pytips Python 2.5 引入了 with 語句(PEP 343)與上下文管理器類型(Context Manager ...

    yuxue 評(píng)論0 收藏0
  • PyTips 0x11 - Python 時(shí)間日期

    摘要:項(xiàng)目地址時(shí)間和日期可能涉及到不同的時(shí)區(qū)格式,同時(shí)又經(jīng)常需要作為時(shí)間戳保存,有時(shí)候還需要進(jìn)行一些加減操作,因此處理起來通常會(huì)因?yàn)榉椒ㄌ喽鵁o從下手。中與時(shí)間和日期相關(guān)的標(biāo)準(zhǔn)庫有個(gè)和。 項(xiàng)目地址:https://git.io/pytips 時(shí)間和日期可能涉及到不同的時(shí)區(qū)、格式,同時(shí)又經(jīng)常需要作為時(shí)間戳保存,有時(shí)候還需要進(jìn)行一些加減操作,因此處理起來通常會(huì)因?yàn)榉椒ㄌ喽鵁o從下手。Python...

    2501207950 評(píng)論0 收藏0
  • PyTips 0x07 - Python 字符串

    摘要:項(xiàng)目地址所有用過的人應(yīng)該都看過下面兩行錯(cuò)誤信息這就是界的錕斤拷今天和接下來幾期的內(nèi)容將主要關(guān)注中的字符串字節(jié)及兩者之間的相互轉(zhuǎn)換。 項(xiàng)目地址:https://git.io/pytips 所有用過 Python (2&3)的人應(yīng)該都看過下面兩行錯(cuò)誤信息: UnicodeEncodeError: ascii codec cant encode characters in position...

    go4it 評(píng)論0 收藏0
  • PyTips 0x05 - Python 函數(shù)參數(shù)解包

    摘要:這里的關(guān)鍵詞函數(shù)必須明確指明,不能通過位置推斷則代表任意數(shù)量的關(guān)鍵詞參數(shù)添加的新特性,使得可以在函數(shù)參數(shù)之外使用這里的逗號(hào)不能漏掉所謂的解包實(shí)際上可以看做是去掉的元組或者是去掉的字典。 項(xiàng)目地址:https://git.io/pytips 函數(shù)調(diào)用的參數(shù)規(guī)則與解包 Python 的函數(shù)在聲明參數(shù)時(shí)大概有下面 4 種形式: 不帶默認(rèn)值的:def func(a): pass 帶有默認(rèn)值的...

    pubdreamcc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<