成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

利用世界杯,讀懂 Python 裝飾器

xiguadada / 2592人閱讀

摘要:今天就結(jié)合最近的世界杯帶大家理解下裝飾器。而德國是上屆的冠軍,又是這屆奪冠熱門。裝飾器的存在是為了適用兩個場景,一個是增強(qiáng)被裝飾函數(shù)的行為,另一個是代碼重用。在利用語法糖,簡化賦值操作。行為良好的裝飾器可以重用,以減少代碼量。

Python 裝飾器是在面試過程高頻被問到的問題,裝飾器也是一個非常好用的特性,
熟練掌握裝飾器會讓你的編程思路更加寬廣,程序也更加 pythonic。

今天就結(jié)合最近的世界杯帶大家理解下裝飾器。

德國戰(zhàn)車

6 月 17 日德國戰(zhàn)墨西哥,小癡雖然是一個偽球迷,但每年的世界杯還是會了解下。而德國是上屆的冠軍,又是這屆奪冠熱門。德意志戰(zhàn)車在 32 年間小組賽就沒有輸過!臥槽!雖然小癡很少賭球,但這次德國如此強(qiáng)大,肯定會贏吧。搏一搏單車變摩托!隨后小癡買了德國隊贏。心里想著這次肯定穩(wěn)了!贏了會所嫩模!小癡連比賽都不看,美滋滋的敲著代碼。

然后比賽結(jié)果卻是德國爆冷 0:1 輸給墨西哥隊,德國隊輸了比賽,小癡也下海干活。只是此時的天臺有點擠,風(fēng)還有大。

小癡含淚的寫下了下面的代碼:

def guess_win(func):
    def rooftop_status():
        result = func()
        print("天臺已滿,請排隊!")
        return result
    return rooftop_status
@guess_win
def german_team():
    print("德國必勝!") 

輸出結(jié)果:

德國必勝!
天臺已滿,請排隊! 
裝飾器是什么

首先我們先來了解下什么是裝飾器,嚴(yán)格來說,裝飾器只是語法糖,裝飾器是可調(diào)用的對象,可以像常規(guī)的可調(diào)用對象那樣調(diào)用,特殊的地方是裝飾器的參數(shù)是一個函數(shù)。

裝飾器的存在是為了適用兩個場景,一個是增強(qiáng)被裝飾函數(shù)的行為,另一個是代碼重用。

比如在上面的例子中我們在壓德國隊贏的時候,原本的 german_team() 函數(shù)只是輸出德國必勝,但在使用裝飾器(guess_win)后,它的功能多了一項:輸出「天臺已滿,請排隊!」。這就是一個簡單的裝飾器,實現(xiàn)了「增強(qiáng)被裝飾函數(shù)的行為」。

一個良好的裝飾器必須要遵守兩個原則:

1 不能修改被裝飾函數(shù)的代碼

2 不能修改被裝飾函數(shù)的調(diào)用方式

這里并不難以理解,在現(xiàn)在的生產(chǎn)環(huán)境中,很多代碼是不能輕易的改寫,因為這樣有可能發(fā)送意想不到的影響。還有一點就是我們在看大神的代碼,我們根本不懂如何改寫。同時你也不能修改調(diào)用方式,因為你并不知道有在一個項目中,有多少處應(yīng)用了此函數(shù)。

裝飾器理解基礎(chǔ)

如果你想要很好的理解裝飾器,那下面的兩個內(nèi)容需要你先有所認(rèn)知。

1 函數(shù)名可以賦值給變量

2 高階函數(shù)

1 函數(shù)名可以賦值給變量

我們來看下這個例子:

def func(name):
    print("我是{}!慌的一逼!".format(name))
func("梅西")
y = func
y("勒夫") 

輸出結(jié)果:

我是梅西!慌的一逼!
我是勒夫!慌的一逼!

在代碼中我們首先定義了函數(shù) func,并調(diào)用了 func 函數(shù),并且把 func 賦值給 y。y = func 表明了:函數(shù)名可以賦值給變量,并且不影響調(diào)用。

這樣講,可能還有些人不太明白。我們在來對比下我們常用的操作。這其實和整數(shù)、數(shù)字是一樣的,下面的代碼你肯定熟悉:

a = 1
b = a
print(a, b) 

2 高階函數(shù)

高階函數(shù)滿足如下的兩個條件中的任意一個:a.可以接收函數(shù)名作為實參;b.返回值中可以包含函數(shù)名。

在 Python 標(biāo)準(zhǔn)庫中的 map 和 filter 等函數(shù)就是高階函數(shù)。

l = [1, 2, 4]
r = map(lambda x: x*3, l)
for i in r:
    print("當(dāng)前天臺人數(shù):", i) 

輸出結(jié)果:

當(dāng)前天臺人數(shù): 3
當(dāng)前天臺人數(shù): 6
當(dāng)前天臺人數(shù): 12 

自定義一個能返回函數(shù)的函數(shù),也是高階函數(shù):

def f(l):
    return map(lambda x: x *5, l)
a = f(l)
for i in a:
    print("當(dāng)前天臺人數(shù):", i) 

輸出結(jié)果:

當(dāng)前天臺人數(shù): 5
當(dāng)前天臺人數(shù): 10
當(dāng)前天臺人數(shù): 20 
實現(xiàn)一個類似的裝飾器

現(xiàn)在你已經(jīng)知道了「函數(shù)名賦值」和「高階函數(shù)」,有了這兩個基礎(chǔ),我們就可以嘗試實現(xiàn)一個類似的裝飾器。

def status(func):
    print("慌的一逼!")
    return func
def name():
    print("我是梅西!")
temp = status(name)
temp() 

輸出結(jié)果:

慌的一逼!
我是梅西! 

在這個例子中我們定義了一個 status 函數(shù),status 接收一個函數(shù)名然后直接返回該函數(shù)名。這樣我們實現(xiàn)了不修改原函數(shù) name,并且添加了一個新功能的需求。但是這里有個缺陷就是函數(shù)的調(diào)用方式改變了。即不是原本的 name,而是 temp。

要解決這個問題很簡單,相信 a = a*3 這樣的表達(dá)式大家都見過,那么上述代碼中的 temp = status(name) 同樣可以修改為 name = status(name),這樣我們就完美的解決了問題:既添加新功能又沒有修改原函數(shù)和其調(diào)用方式。修改后的代碼如下:

def status(func):
    print("慌的一逼!")
    return func
def name():
    print("我是梅西!")
name = status(name)
name() 

但這樣的代碼卻有個不便之處,即每次使用這樣的裝飾器,我們都要寫類似 name = status(name) 的代碼。程序員都是懶的,所以才有那么多高級的語法。在 python 中為了簡化這種情況,提供了一個語法糖 @,在每個被裝飾的函數(shù)上方使用這個語法糖就可以省掉這一句代碼 name = status(name),最后的代碼如下:

def status(func):
    print("慌的一逼!")
    return func
@status
def name():
    print("我是梅西!")
name() 

這樣我們就弄清楚了裝飾器的工作原理:

1 寫一個高階函數(shù),即參數(shù)是函數(shù),返回的也是函數(shù)。

2 在利用語法糖@,簡化賦值操作。

但是對比開頭的例子,還是有些不一樣。在開始的例子中,我們還實現(xiàn)了一個 rooftop_status 函數(shù),來判斷下當(dāng)前的天臺狀是否人滿。但是我們現(xiàn)在是直接返回了函數(shù)名,這樣函數(shù)調(diào)用后我們就沒辦法做任何事情。梅西和德國慌了,我們也慌了,各個都要天臺見,但在這之前我們也要考慮下天臺的情況。

為了能判斷天臺的情況,所以此時我們需要在嵌套一層函數(shù),將實現(xiàn)額外功能的部分寫在內(nèi)層函數(shù)中,然后將這個內(nèi)層函數(shù)返回即可。這也是為什么裝飾器都是嵌套函數(shù)的原因。

另外,開篇的例子并沒有返回值,也沒有參數(shù),要對既有參數(shù)又有返回值的函數(shù)進(jìn)行裝飾的話,還需要進(jìn)一步完善。 能夠處理返回值的裝飾器:

def guess_win(func):
    def rooftop_status():
        result = func()
        print("天臺已滿,請排隊!")
        return result
    return rooftop_status
@guess_win
def german_team():
    print("德國必勝!")
    return "贏了會所嫩模!輸了下海干活!"
x = german_team()
print(x) 

輸出結(jié)果:

德國必勝!
天臺已滿,請排隊!
贏了會所嫩模!輸了下海干活! 

能夠處理參數(shù)的裝飾器:

def guess_win(func):
    def rooftop_status(*args, **kwargs):
        result = func(*args, **kwargs)
        print("天臺已滿,請排隊!")
        return result
    return rooftop_status
@guess_win
def german_team(arg):
    print("{}必勝!".format(arg))
    return "贏了會所嫩模!輸了下海干活!"
x = german_team("德國")
y = german_team("西班牙")
print(x) 

輸出結(jié)果:

德國必勝!
天臺已滿,請排隊!
西班牙必勝!
天臺已滿,請排隊!
贏了會所嫩模!輸了下海干活! 
總結(jié)

裝飾器的本質(zhì)是函數(shù),其參數(shù)是另一個函數(shù)(被裝飾的函數(shù))。裝飾器通常會額外處理被裝飾的函數(shù),然后把它返回,或者將其替換成另一個函數(shù)或可調(diào)用對象。行為良好的裝飾器可以重用,以減少代碼量。

對于這屆的世界杯,我總結(jié)了下。

本文首發(fā)與公眾號「癡海」,后臺回復(fù)「1024」,領(lǐng)取 2018 最新 python 教程。

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42000.html

相關(guān)文章

  • python

    Python裝飾器為什么難理解? 無論項目中還是面試都離不開裝飾器話題,裝飾器的強(qiáng)大在于它能夠在不修改原有業(yè)務(wù)邏輯的情況下對代碼進(jìn)行擴(kuò)展,權(quán)限校驗、用戶認(rèn)證、日志記錄、性能測試、事務(wù)處理、緩存等都是裝飾器的絕佳應(yīng)用場景,它能夠最大程度地對代碼進(jìn)行復(fù)用。 但為什么初學(xué)者對裝飾器的理解如此困難,我認(rèn)為本質(zhì)上是對Py… Python 實現(xiàn)車牌定位及分割 作者用 Python 實現(xiàn)車牌定位及分割的實踐。 ...

    chenatu 評論0 收藏0
  • Python OOP 面向?qū)ο缶幊?/b>

    摘要:時代,如果需要手動繼承,如多態(tài)多態(tài)是指,不同的子類對象調(diào)用相同的父類方法,會產(chǎn)生多態(tài)多樣結(jié)果的編程特性。 參考:黑馬程序員教程 - Python基礎(chǔ) 面向?qū)ο?OOP三大特性,且三個特性是有順序的: 封裝 繼承 多態(tài) 封裝 指的就是把現(xiàn)實世界的事務(wù),封裝、抽象成編程里的對象,包括各種屬性和方法。這個一般都很簡單,不需要多講。 唯一要注意的就是:推薦從小往大開始封裝、開發(fā)類。比如手槍...

    weknow619 評論0 收藏0
  • 利用裝飾python的函數(shù)加上類型限制

    摘要:列表越界的列表類似于動態(tài)數(shù)組,沒有長度的限制。比如對將要傳進(jìn)內(nèi)層函數(shù)的參數(shù)進(jìn)行檢測等,從而實現(xiàn)對參數(shù)的類型進(jìn)行限制。對二維列表的每一維列表進(jìn)行長度限制,不足指定長度,自動補(bǔ)充指定元素。 前言 作為一名python的腦殘粉,請先跟我念一遍python大法好。 其作為動態(tài)語言的靈活,簡介的代碼,確實在某些情況下確實比其他編程語言要好。但你有沒有想過,有時這些靈活的語法,可能會造成一些糟糕的...

    BigTomato 評論0 收藏0
  • python裝飾的原理和使用

    摘要:我們以測量函數(shù)運(yùn)行時間為例來講一講裝飾器的運(yùn)行原理。三更加通用的裝飾器前面兩部分講了裝飾器的原理,這一部分就講講要寫出一個通用的裝飾器需要注意的問題。首先就是參數(shù)的問題,裝飾器返回的函數(shù)不是原來的函數(shù),函數(shù)的簽名也就和原來的函數(shù)簽名不一樣。 一、最簡單的裝飾器 裝飾器是python中很基礎(chǔ)也很實用的一個特性。通過裝飾器我們可以很方便地為一些函數(shù)添加相同的功能。我們以測量函數(shù)運(yùn)行時間為例...

    goji 評論0 收藏0
  • 流暢的python讀書筆記-第七章-函數(shù)裝飾和閉包

    摘要:函數(shù)裝飾器和閉包嚴(yán)格來說,裝飾器只是語法糖。何時執(zhí)行裝飾器它們在被裝飾的函數(shù)定義之后立即運(yùn)行。裝飾器突出了被裝飾的函數(shù)的作用,還便于臨時禁用某個促銷策略只需把裝飾器注釋掉。 函數(shù)裝飾器和閉包 嚴(yán)格來說,裝飾器只是語法糖。如前所示,裝飾器可以像常規(guī)的可調(diào)用對象那樣調(diào)用,其參數(shù)是另一個函數(shù)。有時,這樣做更方便,尤其是做元編程(在運(yùn)行時改變程序的行為)時。 Python何時執(zhí)行裝飾器 它們在...

    Hydrogen 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<