乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Python進(jìn)階系列(五)

       zhulin1028 2022-06-16 發(fā)布于山東

      裝飾器

      使用場(chǎng)景

      現(xiàn)在我們來(lái)看一下裝飾器在哪些地方特別耀眼,以及使用它可以讓一些事情管理起來(lái)變得更簡(jiǎn)單。

      授權(quán)(Authorization)

      裝飾器能有助于檢查某個(gè)人是否被授權(quán)去使用一個(gè)web應(yīng)用的端點(diǎn)(endpoint)。它們被大量

      使用于Flask和Django web框架中。這里是一個(gè)例子來(lái)使用基于裝飾器的授權(quán):

      from functools import wraps
      
      def requires_auth(f):
      
      ??? @wraps(f)
      
      ??? def decorated(*args, **kwargs):
      
      ??????? auth = request.authorization
      
      ??????? if not auth or not check_auth(auth.username, auth.password):
      
      ??????????? authenticate()
      
      ??????? return f(*args, **kwargs)
      
      return decorated

      日志(Logging)

      日志是裝飾器運(yùn)用的另一個(gè)亮點(diǎn)。這是個(gè)例子:

      from functools import wraps
      
      def logit(func):
      
      ??? @wraps(func)
      
      ??? def with_logging(*args, **kwargs):
      
      ??????? print(func.__name__ + " was called")
      
      ??????? return func(*args, **kwargs)
      
      ??? return with_logging
      
      
      @logit
      
      def addition_func(x):
      
      ??? """Do some math."""
      
      ??? return x + x
      
      
      
      result = addition_func(4)
      
      # Output: addition_func was called

      我敢肯定你已經(jīng)在思考裝飾器的一個(gè)其他聰明用法了。

      帶參數(shù)的裝飾器

      來(lái)想想這個(gè)問(wèn)題,難道@wraps不也是個(gè)裝飾器嗎?但是,它接收一個(gè)參數(shù),就像任何普通的函數(shù)能做的那樣。那么,為什么我們不也那樣做呢?

      這是因?yàn)?#xff0c;當(dāng)你使用@my_decorator語(yǔ)法時(shí),你是在應(yīng)用一個(gè)以單個(gè)函數(shù)作為參數(shù)的一個(gè)包裹函數(shù)。記住,Python里每個(gè)東西都是一個(gè)對(duì)象,而且這包括函數(shù)!記住了這些,我們可以編寫(xiě)一下能返回一個(gè)包裹函數(shù)的函數(shù)。

      在函數(shù)中嵌入裝飾器

      我們回到日志的例子,并創(chuàng)建一個(gè)包裹函數(shù),能讓我們指定一個(gè)用于輸出的日志文件。

      from functools import wraps
      
      def logit(logfile='out.log'):
      
      ??? def logging_decorator(func):
      
      ??????? @wraps(func)
      
      ??????? def wrapped_function(*args, **kwargs):
      
      ??????????? log_string = func.__name__ + " was called"
      
      ? ??????????print(log_string)
      
      ??????????? # 打開(kāi)logfile,并寫(xiě)入內(nèi)容
      
      ??????????? with open(logfile, 'a') as opened_file:
      
      ??????????????? # 現(xiàn)在將日志打到指定的logfile
      
      ??????????????? opened_file.write(log_string + '\n')
      
      ??????????? return func(*args, **kwargs)
      
      ??????? return wrapped_function
      
      ??? return logging_decorator
      
      
      
      @logit()
      
      def myfunc1():
      
      ??? pass
      
      
      
      myfunc1()
      
      # Output: myfunc1 was called
      
      # 現(xiàn)在一個(gè)叫做 out.log 的文件出現(xiàn)了,里面的內(nèi)容就是上面的字符串
      
      
      
      @logit(logfile='func2.log')
      
      def myfunc2():
      
      ??? pass
      
      myfunc2()
      
      # Output: myfunc2 was called
      
      # 現(xiàn)在一個(gè)叫做 func2.log 的文件出現(xiàn)了,里面的內(nèi)容就是上面的字符串

      裝飾器類(lèi)

      現(xiàn)在我們有了能用于正式環(huán)境的logit裝飾器,但當(dāng)我們的應(yīng)用的某些部分還比較脆弱時(shí),異常也許是需要更緊急關(guān)注的事情。比方說(shuō)有時(shí)你只想打日志到一個(gè)文件。而有時(shí)你想把引起你注意的問(wèn)題發(fā)送到一個(gè)email,同時(shí)也保留日志,留個(gè)記錄。這是一個(gè)使用繼承的場(chǎng)景,但目前為止我們只看到過(guò)用來(lái)構(gòu)建裝飾器的函數(shù)。

      幸運(yùn)的是,類(lèi)也可以用來(lái)構(gòu)建裝飾器。那我們現(xiàn)在以一個(gè)類(lèi)而不是一個(gè)函數(shù)的方式,來(lái)重新構(gòu)建logit。

      from functools import wraps
      
      class logit(object):
      
      ??? def __init__(self, logfile='out.log'):
      
      ??????? self.logfile = logfile
      
      
      ??? def __call__(self, func):
      
      ??????? @wraps(func)
      
      ??????? def wrapped_function(*args, **kwargs):
      
      ??????????? log_string = func.__name__ + " was called"
      
      ??????????? print(log_string)
      
      ??????????? # 打開(kāi)logfile并寫(xiě)入
      
      ??????????? with open(self.logfile, 'a') as opened_file:
      
      ??????????????? # 現(xiàn)在將日志打到指定的文件
      
      ??????????????? opened_file.write(log_string + '\n')
      
      ??????????? # 現(xiàn)在,發(fā)送一個(gè)通知
      
      ??????????? self.notify()
      
      ??????????? return func(*args, **kwargs)
      
      ??????? return wrapped_function
      
      
      ??? def notify(self):
      
      ??????? # logit只打日志,不做別的
      
      ??????? pass

      這個(gè)實(shí)現(xiàn)有一個(gè)附加優(yōu)勢(shì),在于比嵌套函數(shù)的方式更加整潔,而且包裹一個(gè)函數(shù)還是使用跟以前一樣的語(yǔ)法:

      @logit()
      
      def myfunc1():
      
      ??? pass

      現(xiàn)在,我們給logit創(chuàng)建子類(lèi),來(lái)添加email的功能(雖然email這個(gè)話(huà)題不會(huì)在這里展開(kāi))。

      class email_logit(logit):
      ??? 一個(gè)logit的實(shí)現(xiàn)版本,可以在函數(shù)調(diào)用時(shí)發(fā)送email給管理員

      
      ??? def __init__(self, email='admin@myproject.com', *args, **kwargs)
      
      ??????? self.email = email
      
      ??????? super(logit, self).__init__(*args, **kwargs)
      
      
      ?? ?def notify(self):
      
      ??????? # 發(fā)送一封email到self.email
      
      ??????? # 這里就不做實(shí)現(xiàn)了
      
      ??????? pass

      從現(xiàn)在起,@email_logit將會(huì)和@logit產(chǎn)生同樣的效果,但是在打日志的基礎(chǔ)上,還會(huì)多發(fā)送一封郵件給管理員。

        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多