<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      閉包總結

      一、閉包的本質

      閉包指延伸了作用域的函數,其中包含函數定義體中引用,但是不是定義體中定義的非全局變量。

       

      二、舉例理解概念

      1、函數要求:avg函數,作用是計算不斷增長的系列值的均值;例如,整個歷史中某個商品的平均收盤價。每天都會增加新價格,因此平均值要考慮至目前為止所有的價格。

      >>>avg(10)
      10.0 
      >>>avg(20) 
      15.0
      >>>avg(30)
      20.0 
      

       

      2、實現方式1:使用類實現

      class Averager():
      
          def __init__(self):
              self.series = []
      
          def __call__(self, new_value):
              self.series.append(new_value)
              total = sum(self.series)
              return total/len(self.series)
      
      avg = Averager()
      
      print(avg(10)) #10.0
      print(avg(20)) #15.0
      print(avg(30)) #20.0
      

       函數說明:

        1、定義一個類變量保存價格,avg = Averager() 類的實例化,生成實例對象時,創建self.series,是一個數組。

        2、__call__ 魔法方法:使得 Averager類的 avg 實例對象變成了可調用對象。

        3、每次調用  avg(arg) 時,類變量的列表都增加一個 arg 的元素,返回 列表總和的平均值。

       

      3、實現方式2:使用高階函數實現(把函數作為參數傳入,這樣的函數稱為高階函數)

      def make_averager():
          series = []
      
          def averager(new_value):
              series.append(new_value)
              total = sum(series)
              return total/len(series)
      
          return averager
      
      avg = make_averager()
      print(avg.__code__.co_varnames) #('new_value', 'total')
      print(avg.__code__.co_freevars) #('series',)
      print(avg(10)) #10.0
      print(avg(20)) #15.0
      print(avg(30)) #20.0
      
      print(avg.__closure__) #(<cell at 0x00000151B2C415E8: list object at 0x00000151B2DA7AC8>,)
      print(avg.__closure__[0].cell_contents) #[10, 20, 30]
      

       函數說明:

        1. 調用 make_averager() 時,返回一個 averager 函數對象。每次調用 averager 時,它會把參數添加到系列值中,然后計算平均值。

        2. series 是 make_averager 函數的局部變量

       

      4、方法1和方法2的相通之處和不同之處

       相通:

        調用 Averager() 或 make_averager() 都得到一個可調用對象 avg,它會更新歷史值,然后計算當前均值。

        我們只需要調用 avg(n) ,把n放入到系列值中,然后重新計算均值。

       不同:

        Averager 類的實例 avg 在 self.series 中存儲歷史值;

        make_averager 函數在哪里尋找 series ?series 是 make_averager 函數的局部變量,因為那個函數的定義體中初始化了series, series = [] 。可是調用avg(10)時,make_averager 函數已經返回了,它的本地作用域也一去不復返了。

       

      三、閉包和自由變量

      1、閉包和自由變量:在實現方式2的基礎上

      # 整個部分稱為閉包
          series = []
      
          def averager(new_value):
              series.append(new_value) # series 稱為自由變量
              total = sum(series)
              return total/len(series)
      

       說明:

        averager 的閉包延伸到那個函數的作用域之外,包含自由變量的綁定。

       

      2、func.__code__

        print(avg.__code__.co_varnames) #('new_value', 'total') 將函數參數和局部變量以元組的形式返回

        print(avg.__code__.co_freevars) #('series',) 返回內部函數中引用外部函數參數,即自由變量(通過函數閉包引用)

       

      更詳細的說明參考:

      https://blog.csdn.net/jpch89/article/details/86764245

       

      3、func.__closure__

      # 示例2中
      print(avg.__closure__) #(<cell at 0x00000151B2C415E8: list object at 0x00000151B2DA7AC8>,)
      print(avg.__closure__[0].cell_contents) #[10, 20, 30]
      
      或者遍歷得到:
      [cell.cell_contents for cell in func.__closure__]
      

       

       說明:

        1. Python 3 已將名為func_X 的函數屬性重命名為使用 __X__ 形式,從而在函數屬性名稱空間中為用戶定義的屬性釋放了這些名稱。

        例如,func_closure,func_code,func_defaults,func_dict,func_doc,func_globals,func_name
        分別重命名為__closure__,__code__,__defaults__,__dict__,__doc__,__globals__,__name__。

       

        2. 其實閉包函數相對于普通函數會多出一個closure的屬性,里面定義了一個元組用于存放所有的cell對象,每個cell對象一一保存了這個閉包中所有的外部變量。

        data model將__closure__定義為:None或包含該函數的自由變量綁定的單元格元組。

        如果__closure__不是None,它將創建一個字典,將__code__.co_freevars中的每個單元格名稱映射到元組中的相應cell.cell_contents。

       

        3. “Cell”對象用于實現由多個作用域引用的變量。

        對于每個這樣的變量,一個“Cell”對象為了存儲該值而被創建;引用該值的每個堆棧框架的局部變量包含同樣使用該變量的對外部作用域的“Cell”引用。

        訪問該值時,將使用“Cell”中包含的值而不是單元格對象本身。 這種對“Cell”對象的非關聯化的引用需要支持生成的字節碼;訪問時不會自動非關聯化這些內容。

        “Cell”對象在其他地方可能不太有用。

        引用自:https://docs.python.org/zh-cn/3.7/c-api/cell.html

       

      4、總結

        閉包是一種函數,它會保留定義函數時存在的自由變量的綁定,這樣調用函數時,雖然定義作用域不可用了,但是仍能使用那些綁定。

        注意:只有嵌套在其他函數中的函數,才可能需要處理不在全局作用域中的外部變量。

       

      四、nonlocal 聲明

      1、背景:

        實現方式2中 make_averager 函數的效率并不高;有缺陷。

       

      2、缺陷說明舉例

      >>> def make_averager():
          count = 0
          total = 0
      
          def averager(new_value):
              count += 1
              total +=  new_value
              return total / count
      
          return averager
      
      >>> avg = make_averager()
      >>> avg(10)
      Traceback (most recent call last):
        File "<pyshell#5>", line 1, in <module>
          avg(10)
        File "<pyshell#3>", line 6, in averager
          count += 1
      UnboundLocalError: local variable 'count' referenced before assignment
      >>> 未綁定的局部錯誤:賦值前引用了局部變量“count”
      

       代碼說明:

        當count 是數字,字符串,元組等不可變類型時,count += 1 語句的作用和 count = count+1 一樣。因此我們在averager的定義體中為count賦值了,這會把count變成局部變量。total變量同理。

        在 實現方法2中沒有這個問題是因為沒有給 series 賦值,我們只是調用 series.append ,并把它傳給sum 和 len。也就是說我們利用了列表是可變對象這一事實。

        但是對于不可變類型,只能讀取不可更新。如果嘗試重新綁定,其實會隱式創建局部變量 count。這樣count就不是自由變量了,因此不會保存在閉包中。

        為了解決這個問題,Pyhon 引入了 nonlocal 聲明,它的作用是把變量標記為自由變量,即使在函數中為變量賦予了新值,也會變成自由變量。

        如果為 nonlocal 聲明的變量賦予了新值,閉包中保存的綁定就會更新。

       

      3、實現方式3:nonlocal 實現

      def make_averager():
          count = 0
          total = 0
      
          def averager(new_value):
              nonlocal count,total
              count += 1
              total +=  new_value
              return total / count
      
          return averager
      
      avg = make_averager()
      print(avg(10)) # 10.0
      print(avg(20)) # 15.0
      print(avg(30)) # 20.0
      

       

      posted @ 2021-02-19 00:42  hqq的進階日記  閱讀(159)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩一本不卡一区二区三区| 久久精品国产一区二区三| 宝贝腿开大点我添添公视频免| 中国CHINA体内裑精亚洲日本| 好男人社区影视在线WWW| 看免费的无码区特aa毛片| 97欧美精品系列一区二区| 国精一二二产品无人区免费应用| 亚洲国产精品国自拍av| 国产精品激情av在线播放| 精品日韩人妻中文字幕| 国产激情无码一区二区三区| 国产在线午夜不卡精品影院| 亚洲国产天堂一区二区三区| 精品尤物国产尤物在线看| 成人资源网亚洲精品在线| 夜夜添狠狠添高潮出水| 亚洲国产婷婷综合在线精品| 亚洲性日韩精品一区二区三区 | 亚洲av色图一区二区三区| 88国产精品视频一区二区三区 | 一本色道久久综合亚洲精品| 亚洲日本韩国欧美云霸高清| 亚洲国产精品综合一区二区| 亚洲成年av天堂动漫网站| 在线aⅴ亚洲中文字幕| 亚洲熟妇自偷自拍另欧美| 国产亚洲精品黑人粗大精选| 久爱无码精品免费视频在线观看| 五月丁香六月狠狠爱综合| 清河县| 日本一区二区三区视频版| 久久中文字幕无码一区二区| 久久99精品久久久久久齐齐| 日韩av在线不卡一区二区| 国产成人高清亚洲综合| 成人国产亚洲精品一区二| 中文国产成人精品久久不卡| 亚洲一区二区精品极品| 人妻精品久久无码专区涩涩| 国产成人高清亚洲综合|