python裝飾器入門

来源:https://www.cnblogs.com/failymao/archive/2019/03/01/10454247.html
-Advertisement-
Play Games

[TOC] python裝飾器初級 認識裝飾器 概念: 簡單地說: 原則 : 不修改被裝飾函數的源代碼 不修改被裝飾函數的調用方式 優點: 有助於讓我們的代碼更簡短,也更Pythonic(Python範兒 應用場景: 在項目迭代過程中,需要不停的為某一個功能(函數)新增或刪除某些小功能, 如果可復用 ...


目錄

python裝飾器初級

認識裝飾器

  • 概念:
    • 簡單地說:他們是為其他函數的新增功能的函數
  • 原則 :
    • 不修改被裝飾函數的源代碼
    • 不修改被裝飾函數的調用方式
  • 優點:
    • 有助於讓我們的代碼更簡短,也更Pythonic(Python範兒
  • 應用場景:
    • 在項目迭代過程中,需要不停的為某一個功能(函數)新增或刪除某些小功能, 如果可復用的函數本來比較多, 在如果不停的對原始函數進行修改, 這將會是一件煩躁和重覆的工作. 而使用裝飾器就可以很完美的解決這種問題, 如web用戶的的授權管理,日誌輸出等!

知識儲備

  • 函數即變數

    • 函數本質在電腦的記憶體中的一個單獨記憶體空間, 函數名如同其他類型(int, str, list...)變數名一樣,可以進行賦值,傳遞
  • 嵌套函數 :

    • 定義: 在一個函數中定義另一個函數:

      
      def hi(name="faily"):
          print("now you are inside the hi() function")
      
          def greet():
              return "now you are in the greet() function"
      
          def welcome():
              return "now you are in the welcome() function"
      
          print(greet())
          print(welcome())
          print("now you are back in the hi() function")
      
      if __name__ == "__main__":
          hi()
  • 從函數中返回函數

    • 其實並不需要在一個函數里去執行另一個函數,也可以將其作為輸出返回出來

      def hi(name="faily"):
          def greet():
              return "now you are in the greet() function"
      
          def welcome():
              return "now you are in the welcome() function"
      
          if name == "faily":
              return greet
          else:
              return welcome
      
      if __name__ == "__main__"
          a = hi()        # 此時返回的a實際是greet函數名
          print(a)        # 執行greet函數

      if/else語句中我們返回greetwelcome,而不是greet()welcome()。為什麼那樣?這是因為當你把一對小括弧放在後面,這個函數就會執行;然而如果你不放括弧在它後面,那它可以被到處傳遞,並且可以賦值給別的變數而不去執行它。

      當我們寫下a = hi()hi()會被執行,而由於name參數預設是yasoob,所以函數greet被返回了。如果我們把語句改為a = hi(name = "momo"),那麼welcome函數將被返回。我們還可以列印出hi()(),這會輸出now you are in the greet() function

  • 高階函數

    • 定義: 把一個函數名當作實參傳遞給另外一個函數

      # 計算函數的bar運行時間
      import time
      
      def bar():
          time.sleep(3)
          print("in the bar")
      
      def run_time(func):
          t1 = time.time()
          func()
          t2 = time.time()
          print("the func:{0} run time is {1}".format(func.__name__,t2-t1))
      
      if __name__ == "__main__":
          run_time(bar)
    • 缺點: 雖然實現了此功能,但是改變了 bar函數名

裝飾器演變

  • 實際就是: 高階函數 +嵌套函數的結合體

    認證 裝飾器演變

    • v1 將函數作為參數傳遞進 嵌套函數中, 返回函數本身

      def cert_decorator(func):
      
          def wrapTheFunction():
              user = input("pls input password:").strip()
              if user == "faily":
                  print("---welcome login----")
                  func()
              else:
                  print("----wrong password")
          return wrapper
      
      def task():
          print("do somthing ")
      
      if __name__ == "__main__":
          task = cert_decorator(task)   # 執行裝飾器函數,將task作為參數傳遞,賦值給task變數,返回的是wrapper函數名,內部函數func並沒有執行
          task()                        # 執行task,實際就是執行了wrapper(),然後執行了內部的func()函數

      實現了不改變函數名的和內部結構的前提下, 實現了認證,但是, 但是... 用戶需要多些一行重命名函數變數的方式

    • v2 python內部可以通過@符號進行直接調用

      def cert_decorator(func):
      
          def wrapTheFunction():
              user = input("pls input password:").strip()
              if user == "faily":
                  print("---welcome login----")
                  func()
              else:
                  print("----wrong password")
          return wrapTheFunction
      
      @cert_decorator
      def task():
          print("do somthing ")
      
      if __name__ == "__main__":
          task()

      ※ 好像我們大功告成了... 別高興得太早 ,如果我們運行一下這行代碼 會存在一個問題

      print(task.__name__)
      #output
      wrapTheFunction  

      ♥ . 這並不是我們想要的!Ouput輸出應該是task。這裡的函數被warpTheFunction替代了。它重寫了我們函數的名字和註釋文檔(docstring), 如果我們想在被裝飾的函數在執行之前去訪問函數的某些屬性(文檔, 變數名...),顯然是沒辦法做到的, 怎麼辦???

      幸運的是Python提供給我們一個簡單的函數來解決這個問題,那就是functools.wraps。我們修改上一個例子來使用functools.wraps

    • v3 使用functools.wraps

      from functools import wraps
      
      def cert_decorator(func):
          @wraps(func)
          def wrapTheFunction():
              user = input("pls input password:").strip()
              if user == "faily":
                  print("---welcome login----")
                  func()
              else:
                  print("----wrong password----")
          return wrapTheFunction
      
      @cert_decorator
      def task():
          print("do somthing ")
      
      if __name__ == "__main__":
          task()
          print(task.__name__)
      
      
      # output
      pls input password:mm
      ----wrong password----
      task

      註意:@wraps接受一個函數來進行裝飾,並加入了複製函數名稱、註釋文檔、參數列表等等的功能。這可以讓我們在裝飾器裡面訪問在裝飾之前的函數的屬性。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • LieBrother原文 : "行為型模式:迭代器模式" 十一大行為型模式之六:迭代器模式。 簡介 姓名 :迭代器模式 英文名 :Iterator Pattern 價值觀 :人生沒有回頭路 個人介紹 : Provide a way to access the elements of an aggre ...
  • 定義:用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象 原型模式其實就是通過一個對象來創建一個新的可定製(可以是源對象的一個副本也可以有所改變)的對象,而且我們並不需要知道具體創建的細節。在java中使用原型模式是非常簡單的,因為Object類中提供了一個本地方法clone,就是用來拷 ...
  • PHP語言在Linux系統上運行的時候,需要在Linux系統上部署相應的Nginx、MySQL、PHP等環境,只有將這些環境參數都設置好,PHP相關應用程式才可正常運行,部署環境的方法有很多種,可手動模式下一個個軟體環境進行安裝,也可使用工具進行快速部署,此文以阿裡雲的Centos系統為例,介紹在C ...
  • 這一篇博客,還是接著說那些常見的反爬蟲措施以及我們的解決辦法。同樣的,如果對你有幫助的話,麻煩點一下推薦啦。 一、防盜鏈 這次我遇到的防盜鏈,除了前面說的Referer防盜鏈,還有Cookie防盜鏈和時間戳防盜鏈。Cookie防盜鏈常見於論壇、社區。當訪客請求一個資源的時候,他會檢查這個訪客的Coo ...
  • FPM(FastCGI Process Manager)是PHP FastCGI運行模式的一個進程管理器,從它的定義可以看出,FPM的核心功能是進程管理,那麼它用來管理什麼進程呢?這個問題就需要從FastCGI說起了。 FastCGI是Web伺服器(如:Nginx、Apache)和處理程式之間的一種 ...
  • 裝飾者模式 想看本系列前作的朋友可以點擊下麵鏈接哦。 一起去開心的購物吧——淺談觀察者模式 記一場精彩的籃球比賽——淺談策略模式 大家好,又跟大家見面啦,今天呢,我與大家分享一個新的Java設計模式——裝飾者模式。 首先,不能免俗的我們來看一下官方給的定義: 裝飾者模式動態地將責任附加到對象上。若要 ...
  • 一、前言說明 本機運行環境:系統環境Win10,運行環境Python3.6,運行工具Pycharm 需要Python的包有:pywifi 這是一種暴力破解wifi的模式,需要的時間比較長,本文主要提供一個破解思路 二、思路介紹 先生成一個密碼字典(此步驟也可以從網上下載字典) 迴圈用密碼字典的每個密 ...
  • 安裝 laravel(版本 5.8):這裡是全局安裝的, 也就是說在終端任何位置都可以執行下麵的命令進行安裝. 創建一個項目:安裝之後, 進入你存放所有項目的文件夾(我所有的項目都是在 site 文件夾): 然後新建一個項目, 名字可以自定義. 啟動服務:項目創建好了, 現在進入剛剛創建的項目的文件 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...