最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python閉包技巧介紹

 更新時(shí)間:2021年12月03日 10:11:05   作者:Orion's Blog  
這篇文章主要介紹了Python閉包,所謂閉包就是用函數(shù)代替類,被外層函數(shù)包圍的內(nèi)層函數(shù),它能夠獲取外層函數(shù)范圍中的變量,感興趣的小伙伴請(qǐng)和小編一起進(jìn)入文章學(xué)習(xí)具體內(nèi)容吧

1.閉包:用函數(shù)代替類

有時(shí)我們會(huì)定義只有一個(gè)方法(除了__init__()之外)的類,而這種類可以通過(guò)使用閉包(closure)來(lái)替代。閉包是被外層函數(shù)包圍的內(nèi)層函數(shù),它能夠獲取外層函數(shù)范圍中的變量(即使外層函數(shù)已執(zhí)行完畢)。因此閉包可以保存額外的變量環(huán)境,用于在函數(shù)調(diào)用時(shí)使用。考慮下面這個(gè)例子,這個(gè)類允許用戶通過(guò)某種模板方案來(lái)獲取URL。

from urllib.request import urlopen
class UrlTemplate:
     def __init__(self, template) -> None:
         self.template = template
     def open(self, **kwargs):
         return urlopen(self.template.format_map(kwargs))
    
 yahoo = UrlTemplate('http://finance.yahoo.com/d/quotes.csv?s={names}&f={fields}')
 for line in yahoo.open(names='IBM,AAPL,FB', fields = 'sllclv'):
     print(line.decode('utf-8'))


這個(gè)類可以用一個(gè)簡(jiǎn)單的函數(shù)來(lái)替代:

def urltempalte(template):
    # 后面用對(duì)象再次調(diào)用函數(shù)的時(shí)候傳入kwargs
    def opener(**kwargs):
        return urlopen(template.format_map(kwargs))
    return opener

yahoo = urltempalte('http://finance.yahoo.com/d/quotes.csv?s={names}&f={fields}')
for line in yahoo(names='IBM,AAPL,FB', fields = 'sllclv'):
    print(line.decode('utf-8'))


在許多情況下,我們會(huì)使用只有單個(gè)方法的類的原因是需要保存額外的狀態(tài)給類方法使用。我們上面提到的UrlTemplate類的唯一目的就是將template的值保存在某處,然后在open()方法中使用它。而使用閉包來(lái)解決該問(wèn)題會(huì)更加簡(jiǎn)短和優(yōu)雅,我們使用opener()函數(shù)記住參數(shù)template的值,然后再隨后的調(diào)用中使用該值。
所以大家在編寫代碼中需要附加額外的狀態(tài)給函數(shù)時(shí),一定要考慮使用閉包。

2.訪問(wèn)定義在閉包的內(nèi)的變量

我們知道閉包內(nèi)層可以用來(lái)存儲(chǔ)函數(shù)需要用到的變量環(huán)境。接下來(lái),我們可以通過(guò)函數(shù)來(lái)擴(kuò)展閉包,使得在閉包內(nèi)層定義的變量可以被訪問(wèn)和修改。
一般來(lái)說(shuō),閉包內(nèi)層定義的變量對(duì)外界來(lái)說(shuō)是完全隔離的,如果想要訪問(wèn)和修改它們,需要編寫存取函數(shù)(accessor function, 即getter/setter方法),并將它們做為函數(shù)屬性附加到閉包上來(lái)提供對(duì)內(nèi)層變量的訪問(wèn)支持:

def sample():
    n = 0
    # 閉包函數(shù)
    def func():
        print("n =", n)
    
    # 存取函數(shù)(accessor function),即getter/setter方法
    def get_n():
        return n

    def set_n(value):
        # 必須要加nolocal才能修改內(nèi)層變量
        nonlocal n
        n = value

    # 做為函數(shù)屬性附加
    func.get_n = get_n
    func.set_n = set_n
    return func

該算法測(cè)試運(yùn)行結(jié)果如下:

f = sample()
f() # n = 0
f.set_n(10)
f() # n = 10
print(f.get_n()) # 10


可以看到,get_n()set_n()工作起來(lái)很像實(shí)例的方法。注意一定要將get_n()和set_n()做為函數(shù)屬性附加上去,否則在調(diào)用set_n()get_n()就會(huì)報(bào)錯(cuò):'function' object has no attribute 'set_n'。
如果我們希望讓閉包完全模擬成類實(shí)例,我們需要架構(gòu)內(nèi)層函數(shù)拷貝到一個(gè)實(shí)例的字典中然后將它返回。

示例如下:

import sys
class ClosureInstance:
    def __init__(self, locals=None) -> None:
        if locals is None:
            locals = sys._getframe(1).f_locals 
            
        # Update instance dictionary with callables
        self.__dict__.update(
            (key, value) for key, value in locals.items() if callable(value)
        )

    # Redirect special methods
    def __len__(self):
        return self.__dict__['__len__']()
    
# Example use
def Stack():
    items = []

    def push(item):
        items.append(item)
    
    def pop():
        return items.pop()
    
    def __len__():
        return len(items)
    
    return ClosureInstance()

下面展示了對(duì)應(yīng)的測(cè)試結(jié)果:

s = Stack()
print(s) # <__main__.ClosureInstance object at 0x101efc280>
s.push(10)
s.push(20)
s.push('Hello')
print(len(s)) # 3
print(s.pop()) # Hello
print(s.pop()) # 20
print(s.pop()) # 10


用閉包模型類的功能比傳統(tǒng)的類實(shí)現(xiàn)方法要快一些。比如我們用下面這個(gè)類做為測(cè)試對(duì)比。

class Stack2:
    def __init__(self) -> None:
        self.items = []
    
    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()
    
    def __len__(self):
        return len(self.items)

下面是我們的測(cè)試結(jié)果:

from timeit import timeit
s = Stack()
print(timeit('s.push(1);s.pop()', 'from __main__ import s'))
# 0.98746542
s = Stack2()
print(timeit('s.push(1);s.pop()', 'from __main__ import s'))
# 1.07070521


可以看到采用閉包的版本要快大約8%。因?yàn)閷?duì)于實(shí)例而言,測(cè)試話費(fèi)的大部分時(shí)間都在對(duì)實(shí)例變量的訪問(wèn)上,而閉包要更快一些,因?yàn)椴挥蒙婕邦~外的self變量。
不過(guò)這種奇技淫巧在代碼中還是要謹(jǐn)慎使用,因?yàn)橄啾纫粋€(gè)真正的類,這種方法其實(shí)是相當(dāng)怪異的。像繼承、屬性、描述符或者類方法這樣的特性在這種方法都是無(wú)法使用的。而且我們還需要一些花招才能讓特殊方法正常工作(比如我們上面ClosureInstance中對(duì)__len__()的實(shí)現(xiàn))。不過(guò),這仍然是一個(gè)非常有學(xué)術(shù)價(jià)值的例子,它告訴我們對(duì)閉包內(nèi)部提供訪問(wèn)機(jī)制能夠?qū)崿F(xiàn)怎樣的功能。

到此這篇關(guān)于Python閉包技巧介紹的文章就介紹到這了,更多相關(guān)Python閉包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python設(shè)計(jì)模式之觀察者模式原理與用法詳解

    Python設(shè)計(jì)模式之觀察者模式原理與用法詳解

    這篇文章主要介紹了Python設(shè)計(jì)模式之觀察者模式,簡(jiǎn)單講述了觀察者模式的概念、原理并結(jié)合實(shí)例形式分析了Python實(shí)現(xiàn)與使用方法,需要的朋友可以參考下
    2019-01-01
  • Python中requests庫(kù)的概念及使用詳解

    Python中requests庫(kù)的概念及使用詳解

    這篇文章主要介紹了Python中requests庫(kù)的概念及使用詳解,urllib庫(kù)使用繁瑣,比如處理網(wǎng)頁(yè)驗(yàn)證和Cookies時(shí),需要編寫Opener和Handler來(lái)處理。為了更加方便的實(shí)現(xiàn)這些操作,就有了更為強(qiáng)大的requests庫(kù),需要的朋友可以參考下
    2023-05-05
  • Pytest測(cè)試框架基本使用方法詳解

    Pytest測(cè)試框架基本使用方法詳解

    這篇文章主要介紹了Pytest測(cè)試框架基本使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Python 中使用 Selenium 單擊網(wǎng)頁(yè)按鈕功能

    Python 中使用 Selenium 單擊網(wǎng)頁(yè)按鈕功能

    Selenium是一個(gè)用于測(cè)試網(wǎng)站的自動(dòng)化測(cè)試工具,支持各種瀏覽器包括Chrome、Firefox、Safari等主流界面瀏覽器,同時(shí)也支持phantomJS無(wú)界面瀏覽器,本篇文章將介紹如何在 Python 中使用 selenium 單擊網(wǎng)頁(yè)上的按鈕,感興趣的朋友一起看看吧
    2023-11-11
  • django rest framework 自定義返回方式

    django rest framework 自定義返回方式

    這篇文章主要介紹了django rest framework 自定義返回方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • python執(zhí)行shell并獲取結(jié)果的詳細(xì)示例

    python執(zhí)行shell并獲取結(jié)果的詳細(xì)示例

    在Python中執(zhí)行Shell命令并獲取其結(jié)果,通常可以使用subprocess模塊,這個(gè)模塊允許我們啟動(dòng)新的進(jìn)程,連接到它們的輸入/輸出/錯(cuò)誤管道,并獲取它們的返回碼,下面是一個(gè)詳細(xì)的示例,展示了如何使用subprocess.run()函數(shù)來(lái)執(zhí)行Shell命令并獲取其輸出,需要的朋友可以參考下
    2024-07-07
  • Python爬取某拍短視頻

    Python爬取某拍短視頻

    現(xiàn)在短視頻可謂是一騎絕塵,吃飯的時(shí)候、休息的時(shí)候、躺在床上都在刷短視頻,今天給大家?guī)?lái)python爬蟲進(jìn)階 :美拍視頻地址加密解析,需要的朋友可以參考下
    2021-06-06
  • 關(guān)于SSD目標(biāo)檢測(cè)模型的人臉口罩識(shí)別

    關(guān)于SSD目標(biāo)檢測(cè)模型的人臉口罩識(shí)別

    這篇文章主要介紹了關(guān)于SSD目標(biāo)檢測(cè)模型的人臉口罩識(shí)別問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的貪吃蛇游戲附代碼

    python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的貪吃蛇游戲附代碼

    這篇文章主要介紹了python實(shí)現(xiàn)一個(gè)簡(jiǎn)單的貪吃蛇游戲附代碼,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06
  • python實(shí)現(xiàn)移動(dòng)木板小游戲

    python實(shí)現(xiàn)移動(dòng)木板小游戲

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)移動(dòng)木板小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10

最新評(píng)論

柳河县| 莱西市| 蒙山县| 广平县| 沛县| 罗源县| 宾阳县| 康定县| 连云港市| 盐源县| 永胜县| 莱芜市| 金华市| 民权县| 满洲里市| 横山县| 武定县| 开封县| 广宗县| 白玉县| 峨边| 南澳县| 富阳市| 桂平市| 清远市| 江孜县| 雷山县| 陆良县| 陆川县| 利辛县| 新巴尔虎右旗| 乌兰察布市| 阳山县| 交口县| 昔阳县| 称多县| 志丹县| 平遥县| 海伦市| 固始县| 二手房|