亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

裝飾器

上一篇文章將通過(guò)解決一個(gè)需求問(wèn)題來(lái)了解了閉包,本文也將一樣,通過(guò)慢慢演變一個(gè)需求,一步一步來(lái)了解 Python 裝飾器。

首先有這么一個(gè)輸出員工打卡信息的函數(shù):

def punch():
    print('昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功')
punch()

輸出的結(jié)果如下:

昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功

然后,產(chǎn)品反饋,不行啊,怎么上班打卡沒(méi)有具體的日期,加上打卡的具體日期吧,這應(yīng)該很簡(jiǎn)單,分分鐘解決啦。好吧,那就直接添加打印日期的代碼吧,如下:

import time
def punch():
    print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
    print('昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功')
punch()

輸出結(jié)果如下:

2018-01-09
昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功

這樣改是可以,可是這樣改是改變了函數(shù)的功能結(jié)構(gòu)的,本身這個(gè)函數(shù)定義的時(shí)候就是打印某個(gè)員工的信息和提示打卡成功,現(xiàn)在增加打印日期的代碼,可能會(huì)造成很多代碼重復(fù)的問(wèn)題。比如,還有一個(gè)地方只需要打印員工信息和打卡成功就行了,不需要日期,那么你又要重寫一個(gè)函數(shù)嗎?而且打印當(dāng)前日期的這個(gè)功能方法是經(jīng)常使用的,是可以作為公共函數(shù)給各個(gè)模塊方法調(diào)用的。當(dāng)然,這都是作為一個(gè)整體項(xiàng)目來(lái)考慮的。

既然是這樣,我們可以使用函數(shù)式編程來(lái)修改這部分的代碼。因?yàn)橥ㄟ^(guò)之前的學(xué)習(xí),我們知道 Python 函數(shù)有兩個(gè)特點(diǎn),函數(shù)也是一個(gè)對(duì)象,而且函數(shù)里可以嵌套函數(shù),那么修改一下代碼變成下面這個(gè)樣子:

import time
def punch():
    print('昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功')
def add_time(func):
    print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
    func()
add_time(punch)

輸出結(jié)果:

2018-01-09
昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功

這樣是不是發(fā)現(xiàn),這樣子就沒(méi)有改動(dòng) punch 方法,而且任何需要用到打印當(dāng)前日期的函數(shù)都可以把函數(shù)傳進(jìn) add_time 就可以了,就比如這樣:

import time
def punch():
    print('昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功')
def add_time(func):
    print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
    func()
def holiday():
    print('天氣太冷,今天放假')
add_time(punch)
add_time(holiday)

打印結(jié)果:

2018-01-09
昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功
2018-01-09
天氣太冷,今天放假

使用函數(shù)編程是不是很方便,但是,我們每次調(diào)用的時(shí)候,我們都不得不把原來(lái)的函數(shù)作為參數(shù)傳遞進(jìn)去,還能不能有更好的實(shí)現(xiàn)方式呢?有的,就是本文要介紹的裝飾器,因?yàn)檠b飾器的寫法其實(shí)跟閉包是差不多的,不過(guò)沒(méi)有了自由變量,那么這里直接給出上面那段代碼的裝飾器寫法,來(lái)對(duì)比一下,裝飾器的寫法和函數(shù)式編程有啥不同。

import time
def decorator(func):
    def punch():
        print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
        func()
    return punch
def punch():
    print('昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功')
f = decorator(punch)
f()

輸出的結(jié)果:

2018-01-09
昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功

通過(guò)代碼,能知道裝飾器函數(shù)一般做這三件事:

接收一個(gè)函數(shù)作為參數(shù)

嵌套一個(gè)包裝函數(shù), 包裝函數(shù)會(huì)接收原函數(shù)的相同參數(shù),并執(zhí)行原函數(shù),且還會(huì)執(zhí)行附加功能

返回嵌套函數(shù)

可是,認(rèn)真一看這代碼,這裝飾器的寫法怎么比函數(shù)式編程還麻煩啊。而且看起來(lái)比較復(fù)雜,甚至有點(diǎn)多此一舉的感覺(jué)。

那是因?yàn)槲覀冞€沒(méi)有用到裝飾器的 “語(yǔ)法糖” ,我們看上面的代碼可以知道, Python 在引入裝飾器 (Decorator) 的時(shí)候,沒(méi)有引入任何新的語(yǔ)法特性,都是基于函數(shù)的語(yǔ)法特性。這也就說(shuō)明了裝飾器不是 Python 特有的,而是每個(gè)語(yǔ)言通用的一種編程思想。只不過(guò) Python 設(shè)計(jì)出了 @ 語(yǔ)法糖,讓 定義裝飾器,把裝飾器調(diào)用原函數(shù)再把結(jié)果賦值為原函數(shù)的對(duì)象名的過(guò)程變得更加簡(jiǎn)單,方便,易操作,所以 Python 裝飾器的核心可以說(shuō)就是它的語(yǔ)法糖。

那么怎么使用它的語(yǔ)法糖呢?很簡(jiǎn)單,根據(jù)上面的寫法寫完裝飾器函數(shù)后,直接在原來(lái)的函數(shù)上加 @ 和裝飾器的函數(shù)名。如下:

import time
def decorator(func):
    def punch():
        print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
        func()
    return punch
@decorator
def punch():
    print('昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功')
punch()

輸出結(jié)果:

2018-01-09
昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功

那么這就很方便了,方便在我們的調(diào)用上,比如例子中的,使用了裝飾器后,直接在原本的函數(shù)上加上裝飾器的語(yǔ)法糖就可以了,本函數(shù)也無(wú)虛任何改變,調(diào)用的地方也不需修改。

不過(guò)這里一直有個(gè)問(wèn)題,就是輸出打卡信息的是固定的,那么我們需要通過(guò)參數(shù)來(lái)傳遞,裝飾器該怎么寫呢?裝飾器中的函數(shù)可以使用 *args 可變參數(shù),可是僅僅使用 *args 是不能完全包括所有參數(shù)的情況,比如關(guān)鍵字參數(shù)就不能了,為了能兼容關(guān)鍵字參數(shù),我們還需要加上 **kwargs 。

因此,裝飾器的最終形式可以寫成這樣:

import time
def decorator(func):
    def punch(*args, **kwargs):
        print(time.strftime('%Y-%m-%d', time.localtime(time.time())))
        func(*args, **kwargs)
    return punch
@decorator
def punch(name, department):
    print('昵稱:{0}  部門:{1} 上班打卡成功'.format(name, department))
@decorator
def print_args(reason, **kwargs):
    print(reason)
    print(kwargs)
punch('兩點(diǎn)水', '做鴨事業(yè)部')
print_args('兩點(diǎn)水', sex='男', age=99)

輸出結(jié)果如下:

2018-01-09
昵稱:兩點(diǎn)水  部門:做鴨事業(yè)部 上班打卡成功
2018-01-09
兩點(diǎn)水
{'sex': '男', 'age': 99}

至此,草根學(xué) Python 入門系列文章結(jié)束了。


繼續(xù)學(xué)習(xí)
||
提交重置代碼