1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      python函數(shù)中的閉包 python閉包的條件

      閉包與自由變量

      之前 分析了裝飾器的語法,由此可以直接推導出其基本框架。但為了寫出一個功能完整的裝飾器,還需要了解一個概念——閉包。

      創(chuàng)新互聯(lián)建站是一家專業(yè)提供千陽企業(yè)網(wǎng)站建設,專注與成都網(wǎng)站制作、成都網(wǎng)站設計、H5開發(fā)、小程序制作等業(yè)務。10年已為千陽眾多企業(yè)、政府機構(gòu)等服務。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進行中。

      閉包(closure) ,是引用了自由變量的函數(shù)。 這個被引用的自由變量將和這個函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。

      看下面的例子

      對 f 內(nèi)部的函數(shù) g 來說,參數(shù) a 既不是它的參數(shù),也不是它的局部變量,而是它的自由變量。該自由變量可以

      閉包和嵌套函數(shù)的概念有所區(qū)別。閉包當然是嵌套函數(shù),但沒有引用自由變量的嵌套函數(shù)卻不是閉包。

      Python 的函數(shù)有一個只讀屬性 __closure__ ,存儲的就是函數(shù)所引用的自由變量,

      如果僅僅是嵌套函數(shù),它的 __closure__ 應該是 None 。

      閉包有個重要的特性:內(nèi)部函數(shù)只能引用而不能修改外部函數(shù)中定義的自由變量。試圖直接修改只有兩種結(jié)果,要么運行出錯,要么你以為你修改了,實際并沒有。

      不能修改不是因為 Python 設計者故意限制,不給它權(quán)限,而是外部的自由變量被內(nèi)部的局部變量覆蓋了;被覆蓋了也不是閉包獨有的特性,從普通函數(shù)內(nèi)部同樣也不能直接修改全局變量。Python 命名空間的查找規(guī)則簡寫為 LEGB,四個字母分別代表 local、enclosed、global 和 build-in,閉包外層函數(shù)的命名空間就是 enclosed。Python 在檢索變量時,按照 L - E - G - B 的順序依次查找,如果在 L 中找到了變量,就不會繼續(xù)向后查找。

      在示例 1 中,你的本意是修改自由變量 number ,然而并不能:由于存在對 number 的賦值語句( number += 1 ),Python 會認為 number 是 printer 的局部變量,可是在局部變量字典中又查找不到它的定義,只好拋出異常。拋出的異常不是因為不能修改自由變量,而是局部變量還沒賦值就被引用了。

      在示例 2 中,Python 成功地在 printer 內(nèi)定義了局部變量 number ,并覆蓋了同名自由變量,你可能以為自己成功修改了 print_msg 中的 number ,然而并沒有。

      怎么才能修改呢?

      一種做法是利用可變類型(mutable)的特性,把變量存放在列表(List)之中。對可變的列表的修改并不需要對列表本身賦值, number[0] = 3 只是修改了列表元素。雖然列表發(fā)生了變化,但引用列表的變量卻并沒有改變,巧妙地“瞞”過了 Python。見示例3。

      Python 3 引入了 nonlocal 關(guān)鍵字,明確告訴解釋器:這不是局部變量,要找上外頭找去。在示例 4 中, nonlocal 幫助我們實現(xiàn)了所期望的對自由變量的修改。

      其實,在 Python 2 中,用 global 代替 nonlocal ,也能達到類似的效果,但由于全局變量的不易控制,這種做法不被提倡。

      下面的例子很好地展示了自由變量的特點:與引用它的函數(shù)一同存在,而想要修改它,得小心謹慎。

      裝飾器 rate_limit 的作用,是限制被裝飾的函數(shù)每秒內(nèi)最多被訪問 max_per_sec 次。為此,需要維護一個變量用以記錄上次被調(diào)用的時刻,它獨立于函數(shù)之外,和被修飾的函數(shù)一同存在,還能在每次被調(diào)用的時候更新。 last_time_called 就是這樣的變量。為了正確地更新, last_time_called 以列表的形式存在。如果在 Python 3 中,它也可以直接存為 float ,只要在內(nèi)部函數(shù)中聲明為 nonlocal ,也可以達到同樣的目的。

      python中使用閉包及修改外部函數(shù)的局部變量

      在python中,函數(shù)可以被嵌套定義,也就是說,函數(shù)中可以定義函數(shù)。該函數(shù)還可以將其內(nèi)部定義的函數(shù)作為返回值返回。

      閉包的定義:一般來說,我們可以認為,如果一個函數(shù)可以讀取其他函數(shù)中的局部變量,那么它們就構(gòu)成了閉包。

      注意 :閉包的定義不是特別清晰,但大體上的意思是這樣的。

      我們知道,普通的函數(shù)是可以使用全局變量的

      類似的,函數(shù)中定義的函數(shù),也是可以使用外部函數(shù)的變量的。因此,滿足了函數(shù)讀取了其他函數(shù)局部變量的這一條件,他們因此構(gòu)成了閉包。

      在閉包的使用中,我們可以先給外部的函數(shù)賦予不同的局部變量,然后再調(diào)用其中內(nèi)部的函數(shù)時,就可以讀取到這些不同的局部變量了。

      外部變量的使用 在普通函數(shù)中,雖然可以直接使用全局變量,但是不可以直接修改全局變量。從變量的作用域來說,一旦你嘗試修改全局變量,那么就會嘗試創(chuàng)建并使用一個同名的局部變量。因此,如果你需要在普通函數(shù)中修改全局變量,需要使用global

      同樣的,如果你希望通過定義在內(nèi)部的函數(shù)去修改其外部函數(shù)的變量,那么必須使用nonlocal

      python語言中(1,7,3)的含義)

      自省就是面向?qū)ο蟮恼Z言所寫的程序在運行時,所能知道對象的類型.

      也就是運行時能夠獲得對象的類型.比如type(),dir(),getattr(),hasattr(),isinstance()

      a = [1,2,3]

      b = {'a':1,'b':2,'c':3}

      c = True

      print(type(a),isinstance(b,dict))

      2 Python 中單下劃線和雙下劃線

      _xxx 不能用'from module import *'導入 以單下劃線開頭的表示的是保護類型的變量。即保護類型只能允許其本身與子類進行訪問。

      _ _xxx__ 系統(tǒng)定義的是特列方法。像__init__之類的

      __xxx 類中的私有變量名 雙下劃線的表示的是私有類型的變量。只能是允許這個類本身進行訪問了。連子類也不可以

      3 python中的不定長參數(shù) *args and **kwargs

      不確定函數(shù)里傳遞參數(shù)個數(shù)時可以用*args

      def getall(*args):

      for item in args:

      print(item)

      getall('a','b','c')

      getall(*['a','b','c']) # 打散

      使用沒有事先定義的參數(shù)名kwargs**

      def get_undifined(**kwargs):

      for item in kwargs.items():

      print(item[0],item[1])

      get_undifined(name='amy',age=14) # 打散

      get_undifined(**{'a':1,'b':'hello'}) # 打散

      注意兩者共同使用的時候 位置參數(shù) 要在前

      4 python中裝飾器 與 AOP 面向切面編程

      切面需求: 較為經(jīng)典的有插入日志、性能測試、事務處理等

      而裝飾器這種設計模式 是解決這類問題的絕佳途徑,可以為已經(jīng)存在的對象添加額外的功能

      5 python中鴨子模型

      會鴨子叫的就是鴨子,不關(guān)心對象是什么類型,只關(guān)心對象的特性。

      比如眾多的文件句柄,可迭代對象等具有同一類特征的不同數(shù)據(jù)對象

      鴨子類型在動態(tài)語言中經(jīng)常使用,非常靈活

      6 Python中的作用域

      python中,一個變量的作用域總是由在代碼中被賦值的地方所決定的。

      Python變量的搜索順序:

      本地作用域(Local)→當前作用域被嵌入的本地作用域(Enclosing locals)→全局/模塊作用域(Global)→內(nèi)置作用域(Built-in)

      7 python中的語法結(jié)構(gòu)閉包

      閉包(closure)是函數(shù)式編程的重要的 語法結(jié)構(gòu)。閉包也是一種組織代碼的結(jié)構(gòu),它同樣提高了代碼的可重復使用性。

      當一個內(nèi)嵌函數(shù)引用其外部作作用域的變量,我們就會得到一個閉包. 總結(jié)一下,創(chuàng)建一個閉包必須滿足以下幾點:

      1 必須有一個內(nèi)嵌函數(shù)

      2 內(nèi)嵌函數(shù)必須引用外部函數(shù)中的變量

      3 外部函數(shù)的返回值必須是內(nèi)嵌函數(shù)

      8 python 的 垃圾回收機制

      Python垃圾回收機制

      Python GC主要使用 引用計數(shù)(reference counting)來跟蹤和回收垃圾。在引用計數(shù)的基礎上,通過“標記-清除”(mark and sweep)

      解決容器對象可能產(chǎn)生的循環(huán)引用問題,通過“分代回收”(generation collection)以空間換時間的方法提高垃圾回收效率。

      1 引用計數(shù)

      PyObject是每個對象必有的內(nèi)容,其中ob_refcnt就是做為引用計數(shù)。當一個對象有新的引用時,它的ob_refcnt就會增加,

      當引用它的對象被刪除,它的ob_refcnt就會減少.引用計數(shù)為0時,該對象生命就結(jié)束了。

      2 標記-清除機制

      基本思路是先按需分配,等到?jīng)]有空閑內(nèi)存的時候從寄存器和程序棧上的引用出發(fā),遍歷以對象為節(jié)點、以引用為邊構(gòu)成的圖,

      把所有可以訪問到的對象打上標記,然后清掃一遍內(nèi)存空間,把所有沒標記的對象釋放。

      3 分代技術(shù)

      分代回收的整體思想是:將系統(tǒng)中的所有內(nèi)存塊根據(jù)其存活時間劃分為不同的集合,每個集合就成為一個“代”,

      垃圾收集頻率隨著“代”的存活時間的增大而減小,存活時間通常利用經(jīng)過幾次垃圾回收來度量。

      Python默認定義了三代對象集合,索引數(shù)越大,對象存活時間越長。

      9 python種類以及與其他計算機語言類型對比

      C語言: 代碼編譯得到機器碼 ,機器碼在處理器上直接執(zhí)行,每一條指令控制CPU工作–速度較快

      Java,c#,python,php 其他語言: 代碼編譯得到字節(jié)碼 ,虛擬機執(zhí)行字節(jié)碼并轉(zhuǎn)換成機器碼再后在處理器上執(zhí)行—-速度慢

      python的種類

      Cpython

      Python的官方版本,使用C語言實現(xiàn),使用最為廣泛,

      CPython實現(xiàn)會將源文件(py文件)轉(zhuǎn)換成字節(jié)碼文件

      (pyc文件),然后運行在Python虛擬機上。

      Jyhton

      Python的Java實現(xiàn),Jython會將Python代碼動態(tài)編譯成Java

      字節(jié)碼,然后在JVM上運行。

      IronPython

      Python的C#實現(xiàn),IronPython將Python代碼編譯成C#字節(jié)

      碼,然后在CLR上運行。(與Jython類似)

      PyPy(特殊)

      Python實現(xiàn)的Python,將Python的字節(jié)碼字節(jié)碼再編譯成機器

      碼。

      9 python PEP8 編碼規(guī)范

      一 代碼編排

      1 縮進。4個空格的縮進(編輯器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。

      2 每行最大長度79,換行可以使用反斜杠,最好使用圓括號。換行點要在操作符的后邊敲回車。

      3 類和top-level函數(shù)定義之間空兩行;類中的方法定義之間空一行;函數(shù)內(nèi)邏輯無關(guān)段落之間空一行;其他地方盡量不要再空行。

      二 文檔編排

      1 模塊內(nèi)容的順序:模塊說明和docstring—import—globalsconstants—其他定義。其中import部分,又按標準、三方和自己編寫順序依次排放,之間空一行。

      2 不要在一句import中多個庫,比如import os, sys不推薦。

      3 如果采用from XX import XX引用庫,可以省略‘module.’,都是可能出現(xiàn)命名沖突,這時就要采用import XX。

      三 空格的使用

      總體原則,避免不必要的空格。

      1 各種右括號前不要加空格。

      2 逗號、冒號、分號前不要加空格。

      3 函數(shù)的左括號前不要加空格。如Func(1)。

      4 序列的左括號前不要加空格。如list[2]。

      5 操作符左右各加一個空格,不要為了對齊增加空格。

      6 函數(shù)默認參數(shù)使用的賦值符左右省略空格。

      7 不要將多句語句寫在同一行,盡管使用‘;’允許。

      8 if/for/while語句中,即使執(zhí)行語句只有一句,也必須另起一行。

      四 注釋

      注釋必須使用英文,最好是完整的句子,首字母大寫,句后要有結(jié)束符,結(jié)束符后跟兩個空格,開始下一句。如果是短語,可以省略結(jié)束符。

      1 塊注釋,在一段代碼前增加的注釋。在‘#’后加一空格。段落之間以只有‘#’的行間隔。比如:

      2 行注釋,在一句代碼后加注釋。比如:x = x + 1 # Increment x但是這種方式盡量少使用。

      3 避免無謂的注釋。

      五 文檔描述

      1 為所有的共有模塊、函數(shù)、類、方法寫docstrings;非共有的沒有必要,但是可以寫注釋(在def的下一行)。

      2 如果docstring要換行,參考如下例子,詳見PEP 257

      六 命名規(guī)范

      新編代碼必須按下面命名風格進行,現(xiàn)有庫的編碼盡量保持風格。

      1 盡量單獨使用小寫字母‘l’,大寫字母‘O’等容易混淆的字母。

      2 模塊命名盡量短小,使用全部小寫的方式,可以使用下劃線。

      3 包命名盡量短小,使用全部小寫的方式,不可以使用下劃線。

      4 類的命名使用CapWords的方式,模塊內(nèi)部使用的類采用_CapWords的方式。

      5 異常命名使用CapWords+Error后綴的方式。

      6 全局變量盡量只在模塊內(nèi)有效,類似C語言中的static。實現(xiàn)方法有兩種,一是__all__機制;二是前綴一個下劃線。

      7 函數(shù)命名使用全部小寫的方式,可以使用下劃線。

      8 常量命名使用全部大寫的方式,可以使用下劃線。

      9 類的屬性(方法和變量)命名使用全部小寫的方式,可以使用下劃線。

      9 類的屬性有3種作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public屬性前,前綴一條下劃線。

      11 類的屬性若與關(guān)鍵字名字沖突,后綴一下劃線,盡量不要使用縮略等其他方式。

      12 為避免與子類屬性命名沖突,在類的一些屬性前,前綴兩條下劃線。比如:類Foo中聲明__a,訪問時,只能通過Foo._Foo__a,避免歧義。如果子類也叫Foo,那就無能為力了。

      13 類的方法第一個參數(shù)必須是self,而靜態(tài)方法第一個參數(shù)必須是cls。

      七 編碼建議

      1 編碼中考慮到其他python實現(xiàn)的效率等問題,比如運算符‘+’在CPython(Python)中效率很高,都是Jython中卻非常低,所以應該采用.join()的方式。

      2 盡可能使用‘is’‘is not’取代‘==’,比如if x is not None 要優(yōu)于if x。

      3 使用基于類的異常,每個模塊或包都有自己的異常類,此異常類繼承自Exception。

      4 異常中不要使用裸露的except,except后跟具體的exceptions。

      5 異常中try的代碼盡可能少。比如:

      6 使用startswith() and endswith()代替切片進行序列前綴或后綴的檢查。比如

      7 使用isinstance()比較對象的類型。比如

      8 判斷序列空或不空,有如下規(guī)則

      9 字符串不要以空格收尾。

      10 二進制數(shù)據(jù)判斷使用 if boolvalue的方式。

      Python嵌套函數(shù)和閉包

      在Python語言中,可以在函數(shù)中定義函數(shù)。 這種在函數(shù)中嵌套定義的函數(shù)也叫內(nèi)部函數(shù)。我們來看下面的代碼:

      上述代碼中,定義了函數(shù)greet,在函數(shù)greet內(nèi)部又定義了一個函數(shù)inner_func, 并調(diào)用該函數(shù)打印了一串字符。

      我們可以看到,內(nèi)部函數(shù)inner_func的定義和使用與普通函數(shù)基本相同。需要注意的是變量的作用域,在上述代碼中,函數(shù)參數(shù)name對于全局函數(shù)greet是局部變量,對內(nèi)部函數(shù)inner_func來說則是非局部變量。內(nèi)部函數(shù)對于非局部變量的訪問規(guī)則類似于標準的外部函數(shù)訪問全局變量。

      從這個例子我們還可以看到內(nèi)部函數(shù)的一個作用,就是通過定義內(nèi)部函數(shù)的方式將一些功能隱藏起來,防止外部直接調(diào)用。常見的場景是,在一個復雜邏輯的函數(shù)中,將一些小的任務定義成內(nèi)部函數(shù),然后由這個外層函數(shù)使用,這樣可以使代碼更為清晰,易于維護。這些內(nèi)部函數(shù)只會在這個外層函數(shù)中使用,不能被其他函數(shù)或模塊使用。

      在Python語言中, 函數(shù)也是對象,它可以被創(chuàng)建、賦值給變量,或者作為函數(shù)的返回值。我們來看下面這個例子。

      在上述代碼中,在函數(shù)gen_greet內(nèi)部定義了inner_func函數(shù),并返回了一個inner_func函數(shù)對象。外部函數(shù)gen_greet返回了一個函數(shù)對象,所以像gen_greet這樣的函數(shù)也叫工廠函數(shù)。

      在內(nèi)部函數(shù)inner_func中,使用了外部函數(shù)的傳參greet_words(非局部變量),以及函數(shù)的參數(shù)name(局部變量),來打印一個字符串。

      接下來,調(diào)用gen_greet("Hello")創(chuàng)建一個函數(shù)對象say_hello,緊接著調(diào)用say_hello("Mr. Zhang"),輸出的結(jié)果為:Hello, Mr. Zhang!

      同樣的,調(diào)用gen_greet("Hi")創(chuàng)建一個函數(shù)對象say_hi,調(diào)用say_hello("Mr. Zhang"),輸出的結(jié)果為:Hi,Tony!

      我們可以發(fā)現(xiàn),gen_greet返回的函數(shù)對象具有記憶功能,它能夠把所需使用的非局部變量保存下來,用于后續(xù)被調(diào)用的時候使用。這種保存了非局部變量的函數(shù)對象被稱作閉包(closure)。

      那么閉包是如何實現(xiàn)的呢?其實并不復雜,函數(shù)對象中有一個屬性__closure__,它就是在創(chuàng)建函數(shù)對象時用來保存這些非局部變量的。

      __closure__屬性是一個元組或者None類型。在上述代碼中,我們可以通過下面方式查看:

      函數(shù)的嵌套所實現(xiàn)的功能大都可以通過定義類的方式來實現(xiàn),而且類是更加面向?qū)ο蟮拇a編寫方式。

      嵌套函數(shù)的一個主要用途是實現(xiàn)函數(shù)的裝飾器。我們看下面的代碼:

      在上述代碼中,logger函數(shù)返回函數(shù)with_logging,with_logging則是打印了函數(shù)func的名稱及傳入的參數(shù),然后調(diào)用func, 并將參數(shù)傳遞給func。其中的@wraps(func)語句用于復制函數(shù)func的名稱、注釋文檔、參數(shù)列表等等,使得with_logging函數(shù)具有被裝飾的函數(shù)func相同的屬性。

      代碼中接下來用@logger對函數(shù)power_func進行修飾,它的作用等同于下面的代碼:

      可見,裝飾器@符其實就是上述代碼的精簡寫法。

      通過了解了嵌套函數(shù)和閉包的工作原理,我們在使用過程中就能夠更加得心應手了。


      文章題目:python函數(shù)中的閉包 python閉包的條件
      當前網(wǎng)址:http://www.ef60e0e.cn/article/doedeii.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        镇坪县| 义乌市| 育儿| 靖江市| 秭归县| 铜川市| 南昌县| 会同县| 上饶县| 南和县| 道真| 江口县| 灌阳县| 监利县| 怀宁县| 沂南县| 华坪县| 太原市| 霍邱县| 岗巴县| 赣榆县| 宝丰县| 延安市| 儋州市| 双流县| 永州市| 中牟县| 兴宁市| 锡林浩特市| 陇南市| 仙游县| 金沙县| 九江县| 江西省| 西青区| 扎囊县| 昔阳县| 西宁市| 海安县| 漯河市| 新建县|