Python裝飾器總結(jié),帶你幾步跨越此坑!

      網(wǎng)友投稿 1031 2022-05-30

      關(guān)于訴求

      昨天簡(jiǎn)單聊了下Flask的學(xué)習(xí)感想,然后分享了一些Flask的學(xué)習(xí)方式與視頻。其中提到在學(xué)習(xí)Python Web前,請(qǐng)先將python基礎(chǔ)及裝飾器等知識(shí)有一個(gè)了解,這樣學(xué)習(xí)起來(lái)不至于太過(guò)吃力。

      然后,今天有朋友私信說(shuō)對(duì)python的類和裝飾器不甚了解,希望能講講這些知識(shí)。關(guān)于函數(shù)、方法、類,我之前發(fā)過(guò)一篇文章,就不再贅述了。其實(shí)去年詳細(xì)總結(jié)過(guò)一篇關(guān)于Python裝飾器的文章,只不過(guò)是在公司博客寫的,沒(méi)辦法復(fù)制出來(lái),所以今天就這之前的知識(shí)做一個(gè)總結(jié)和復(fù)習(xí)吧。

      引子

      談及python裝飾器,很多人第一時(shí)間想到的是@這個(gè)符號(hào)。在方法上一行加上@decorator就行了。但很多人看著都會(huì)、一用就跪,而且很多時(shí)候,我們都不知道什么場(chǎng)景下適合使用裝飾器。那么今天就帶大家一步步了解裝飾器的使用吧

      裝飾器(Decorator)是python的一個(gè)重要部分,簡(jiǎn)單來(lái)說(shuō),他是修改其他函數(shù)功能的函數(shù)。

      他們有助于讓我們的代碼更簡(jiǎn)短,也更Pythonic!

      萬(wàn)物皆對(duì)象

      在Python的世界中,萬(wàn)物皆對(duì)象,聽起來(lái)比較抽象,但其實(shí)理解起來(lái)很簡(jiǎn)單,你可以用將任何一個(gè)變量、函數(shù)、方法、類等等賦值給另一個(gè)變量。只有你了解了這些,才能進(jìn)一步的理解裝飾器。

      函數(shù)賦值

      而學(xué)習(xí)裝飾器前,我們先來(lái)舉一個(gè)簡(jiǎn)單的函數(shù)例子:

      def hello(name='BreezePython'):

      return "say hello to {}".format(name)

      hello()

      # 'say hello to BreezePython'

      hi = hello

      hi('tommorow')

      # 'say hello to tommorow'

      我們首先創(chuàng)建一個(gè)hello的函數(shù),然后調(diào)用,之后將hello賦值給hi,之后調(diào)用hi,完成了相同的操作,也許你覺(jué)得這個(gè)例子so easy,那就接著往下走。

      函數(shù)嵌套

      當(dāng)我們?cè)诤瘮?shù)中再次定義一個(gè)函數(shù)是,即完成了一個(gè)函數(shù)的嵌套操作:

      def hello():

      print('is hello function...')

      def hi():

      return 'hi ,nice to meet you!'

      def bye():

      return 'bye,stranger...'

      print(hi())

      print(bye())

      hello()

      output:

      is hello function...

      hi ,nice to meet you!

      bye,stranger...

      hi()

      output:

      Traceback (most recent call last):

      File "", line 1, in

      NameError: name 'hi' is not defined

      上面的例子看到了,函數(shù)中可以調(diào)用子函數(shù),但如果你直接去調(diào)用子函數(shù),則會(huì)拋出未定義的異常,那么我們?nèi)绾握{(diào)用子函數(shù)?

      函數(shù)中返回函數(shù)

      讓我們由淺入深,先考慮從函數(shù)中返回函數(shù)

      def hello(name=None):

      print('is hello function...')

      def hi():

      return 'hi ,nice to meet you!'

      def bye():

      return 'bye,stranger...'

      if name == 'BreezePython':

      return hi

      else:

      return bye

      main = hello('BreezePython')

      >>> output: is hello function...

      main()

      >>> output: 'hi ,nice to meet you!'

      初學(xué)者可能對(duì)python中的小括號(hào)有些迷糊,添加小括號(hào)與否有什么影響呢?

      函數(shù)作為參數(shù)傳遞

      def child():

      return 'is child function...'

      def main(func):

      print('is main function...')

      print(func())

      main(child)

      Python裝飾器總結(jié),帶你幾步跨越此坑!

      output:

      >>> is main function...

      >>> is child function...

      我們新建了一個(gè)child函數(shù),然后將child話術(shù)傳遞給main函數(shù),在main函數(shù)中調(diào)用child函數(shù),達(dá)到了將函數(shù)作為參數(shù)傳遞的結(jié)果。

      python閉包

      我們先將上面的函數(shù)嵌套與傳參來(lái)進(jìn)行一下合并:

      def main(func):

      print('is main function...')

      def child():

      print('it print before exec func...')

      func()

      print('it print after exec func...')

      return child

      def alone():

      print("I'm ?alone function ...")

      fix = main(alone)

      fix()

      output:

      >>> is main function...

      >>> it print before exec func...

      >>> I'm ?alone function ...

      >>> it print after exec func...

      通過(guò)合并,我們將上面兩個(gè)例子進(jìn)行和組裝,變成了一個(gè)升級(jí)版的閉包,很多人會(huì)說(shuō),什么是閉包呢?其實(shí)很簡(jiǎn)單…

      first Decorator

      上面的例子中,我們看到了一個(gè)閉包與函數(shù)傳參的例子,那么裝飾器是什么?其實(shí)就是閉包+函數(shù)傳參,如果上面的例子你看懂了,那么現(xiàn)在你只需要對(duì)代碼格式稍作修改,就變成了一個(gè)裝飾器!

      def main(func):

      print('is main function...')

      def child():

      print('it print before exec func...')

      func()

      print('it print after exec func...')

      return child

      @main

      def alone():

      print("I'm ?alone function ...")

      alone()

      # output:

      >>> is main function...

      >>> it print before exec func...

      >>> I'm ?alone function ...

      >>> alone

      >>> it print after exec func...

      我們只是修改了一行代碼的格式,就轉(zhuǎn)化成了裝飾器,@main就代表func = main(func)

      可這樣就算完美的裝飾器了么?NO….

      我們將alone函數(shù)稍作變更,即可看出問(wèn)題所在:

      def alone():

      print("I'm ?alone function ...")

      print(alone.__name__)

      正常情況下,調(diào)用alone帶引的alone.__name__就是函數(shù)名即alone,但如果我們是通過(guò)裝其實(shí)調(diào)用后打印呢,結(jié)果是什么?相信大家能猜到,是child。child是main函數(shù)的內(nèi)建函數(shù),它重寫了我們的函數(shù)名,如何解決這個(gè)問(wèn)題呢?

      from functools import wraps

      # first Decorator

      def main(func):

      print('is main function...')

      @wraps(func)

      def child():

      print('it print before exec func...')

      func()

      print('it print after exec func...')

      return child

      @main

      def alone():

      print("I'm ?alone function ...")

      print(alone.__name__)

      alone()

      # output:

      >>> is main function...

      >>> it print before exec func...

      >>> I'm ?alone function ...

      >>> alone

      >>> it print after exec func...

      我們通過(guò)引入functools方法中的wraps,保證了函數(shù)名稱的原始性

      @wraps接受一個(gè)函數(shù),進(jìn)行裝飾,并加入了復(fù)制函數(shù)名稱、注釋文檔、參數(shù)列表等功能,這樣可以是我們?cè)谘b飾器里面訪問(wèn)在裝飾之前的函數(shù)的屬性

      裝飾器實(shí)例

      裝飾器比大量的使用在Flask、Django中,學(xué)好了它不管是對(duì)于你理解flask的路由,還是之后的代碼開發(fā)都有很多幫助,那么我們來(lái)做個(gè)簡(jiǎn)單的例子,日志打印裝飾器:

      import time

      from functools import wraps

      def log_level(level='DEBUG'):

      def log_format(func):

      @wraps(func)

      def format(*args, **kwargs):

      logtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())

      print("[{}]{}: ".format(level, logtime), end='')

      return func(*args, **kwargs)

      return format

      return log_format

      @log_level()

      def log1():

      print("Hello,Welcome to 清風(fēng)Python...")

      @log_level('ERROR')

      def log2():

      print("清風(fēng)Python 是我的公眾號(hào)...")

      log1()

      time.sleep(1)

      log2()

      # output:

      >>> [DEBUG]2019-08-20 01:24:23: Hello,Welcome to 清風(fēng)Python...

      >>> [ERROR]2019-08-20 01:24:24: 清風(fēng)Python 是我的公眾號(hào)...

      類的裝飾器

      講了這么多,本來(lái)覺(jué)得該結(jié)束了,可總覺(jué)得還差點(diǎn)什么!沒(méi)錯(cuò),我們只是講到了函數(shù)的裝飾器,那么類的裝飾器該如何操作呢?

      import time

      from functools import wraps

      class Logger:

      def __init__(self,level='DEBUG'):

      self.level = level

      def __call__(self, func):

      @wraps(func)

      def log_format(*args, **kwargs):

      log_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())

      print("[{}]{}: ".format(self.level, log_time), end='')

      return func(*args, **kwargs)

      return log_format

      @Logger()

      def log1():

      print("Hello,Welcome to 清風(fēng)Python...")

      @Logger('Error')

      def log2():

      print("清風(fēng)Python 是我的公眾號(hào)...")

      log1()

      time.sleep(1)

      log2()

      # output:

      >>> [DEBUG]2019-08-20 01:24:23: Hello,Welcome to 清風(fēng)Python...

      >>> [ERROR]2019-08-20 01:24:24: 清風(fēng)Python 是我的公眾號(hào)...

      今天的裝飾器內(nèi)容就分享到這里吧…

      The End

      OK,今天的內(nèi)容就到這里,歡迎大家關(guān)注“清風(fēng)Python”公眾號(hào)

      python

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:大數(shù)據(jù)可視洞察Davinci的安裝與配置攻略
      下一篇:《Spark Streaming實(shí)時(shí)流式大數(shù)據(jù)處理實(shí)戰(zhàn)》 ——2.3 搭建開發(fā)環(huán)境
      相關(guān)文章
      亚洲精品乱码久久久久久自慰| 久久久久亚洲AV无码去区首| 亚洲色偷拍区另类无码专区| 亚洲色www永久网站| 精品亚洲AV无码一区二区三区 | 日本久久久久亚洲中字幕| av在线亚洲欧洲日产一区二区| 亚洲欧洲久久av| 亚洲熟伦熟女新五十路熟妇 | 一本色道久久88亚洲综合| 亚洲AV无码片一区二区三区 | 亚洲国产成人精品久久久国产成人一区二区三区综 | 亚洲AV无码一区二区乱孑伦AS| 亚洲精品乱码久久久久久蜜桃不卡| 亚洲日本乱码在线观看| 国产v亚洲v天堂无码网站| 亚洲va国产va天堂va久久| 亚洲国产综合专区在线电影| 337p日本欧洲亚洲大胆艺术| 亚洲成年人电影网站| 在线精品亚洲一区二区| 亚洲av色香蕉一区二区三区 | 亚洲国产天堂久久综合| 亚洲无人区一区二区三区| 国产成人A人亚洲精品无码| 亚洲综合无码一区二区| 亚洲成aⅴ人片在线影院八| 亚洲中文字幕一二三四区| 色噜噜噜噜亚洲第一| av在线亚洲欧洲日产一区二区| 亚洲精品夜夜夜妓女网| 亚洲A∨无码无在线观看| 91亚洲国产成人久久精品| 亚洲成_人网站图片| 狼人大香伊蕉国产WWW亚洲| 国产亚洲精品a在线观看| 久久91亚洲人成电影网站| 亚洲综合图片小说区热久久| 国产亚洲精品VA片在线播放| 一本久久综合亚洲鲁鲁五月天| 国产成人亚洲精品狼色在线|