裝飾器語法糖運用

裝飾器語法糖運用

  • 前言:函數名是一個特性的變量,能夠做爲容器的元素,也能夠做爲函數的參數,也能夠當作返回值。python

  • 閉包定義:閉包

    • 內層函數對外層函數(非全局)變量的引用,這個內層函數就能夠成爲閉包app

    • 在Python中咱們用__closure__來檢查函數是不是閉包函數

    • def func1():
          name = '張三'
      
          def func2():
              print(name)  # 可以訪問到外層做用域的變量
          func2()
          print(func2.__closure__)  # (<cell at 0x1036c7438: str object at 0x10389d088>,)
      
      func1()
      print(func1.__closure__)  # None
  • 裝飾器

    • 前言:軟件設計原則:開閉原則,又稱開放封閉原則工具

      • 指對擴展代碼的功能是開放的,但對修改源代碼是封閉的,
    • def create_people():
          print('女媧真厲害,捏個泥吹口氣就成了人!')
      
      
      def a(func):
          def b():
              print('灑點水')
              func()
          return b
      
      ret = a(create_people)
      ret()
    • 經過裝飾器語法等同於設計

    • def a(func):
          def b():
              print('灑點水')
              func()
          return b
      
      
      @a  # 裝飾器語法糖的做用就是上述函數ret()
      def create_people():
          print('女媧真厲害,捏個泥吹口氣就成了人!')
      
      create_people()
  • 裝飾帶返回值的函數,即return出被裝飾函數的執行結果code

    • def foo(func):  # 接收的參數是一個函數名
          def bar():  # 定義一個內層函數
              print("這裏是新功能...")  # 新功能
              r = func()  # 在內存函數中拿到被裝飾函數的結果
              return r  # 返回被裝飾函數的執行結果
          return bar
      
      
      # 定義一個有返回值的函數
      @foo
      def f1():
          return '嘿嘿嘿'
      
      
      # 調用被裝飾函數
      ret = f1()  # 調用被裝飾函數並拿到結果
      print(ret)
  • 裝飾帶參數的函數orm

    • def func1(func):              # 接收的參數爲一個函數名
          def inner(*args, **kwargs):     # 這裏須要定義和被裝飾函數相同的參數
              print("新功能")                # 新功能
              ret = func(*args, **kwargs)     #被裝飾的函數和參數
              print("新功能")         
              return ret
          return inner
      
      # 定義一個須要倆個參數的函數
      @func1
      def func(a, b):
          return a + b
      
      
      ret = func(3, 5)
      print(ret)
  • 帶參數的裝飾器 即在裝飾器外在寫一層函數,從而使其帶參數內存

    • def d(a=None):        # 定義一個外層函數,給裝飾器傳參數
          def func1(func):  # 接收的是一個函數名
              def inner(*args, **kwargs): # 被裝飾的函數,和參數
                  if a:
                      print(f"歡迎來到{a}")   #添加新功能
                  else:
                      print("歡迎來到王者榮耀")  
                  func(*args, **kwargs)
              return inner
          return func1
      
      
      # @d("英雄聯盟")
      # def func(st):
      #     print(st)
      # func("敵軍還有三十秒到達戰場")
                                    # 歡迎來到英雄聯盟
                                    # 敵軍還有三十秒到達戰場
      
      @d()
      def func(st):
          print(st)
      func("敵軍還有三十秒到達戰場")
      # 歡迎來到王者榮耀
      # 敵軍還有三十秒到達戰場
  • 裝飾器修復技術作用域

    • 定義:被裝飾的函數最終都會失去原本的__doc__等信息, Python給咱們提供了一個修復被裝飾函數的工具。

    • from functools import wraps    #導入
      print(f1.__doc__)
      print(f1.__name__)
  • 多個裝飾器裝飾同一函數

    • from functools import wraps
      
      def wrapper2(func):
          @wraps(func)
          def inner(*args, **kwargs):
              r = func(*args, **kwargs)
              return f"<2>{r}</2>"
          return inner
      
      def wrapper1(func):
          @wraps(func)
          def inner(*args, **kwargs):
              r = func(*args, **kwargs)
              return f"<1>{r}</1>"
          return inner
      
      @wrapper2
      @wrapper1
      def func(a):
          return a
      
      
      print(func("Hello World!!"))  #<2><1>Hello World!!</1></2>
    • def foo1(func):
          print("d1")
      
          def inner1():
              print("inner1")
              return "<i>{}</i>".format(func())
      
          return inner1
      
      
      def foo2(func):
          print("d2")
      
          def inner2():
              print("inner2")
              return "<b>{}</b>".format(func())
      
          return inner2
      
      
      @foo1
      @foo2
      def f1():
          return "Hello Andy"
      
      # f1 = foo2(f1)  ==> print("d2") ==> f1 = inner2
      # f1 = foo1(f1)  ==> print("d1") ==> f1 = foo1(inner2) ==> inner1
      
      ret = f1()  # 調用f1() ==> inner1()  ==> <i>inner2()</i>  ==> <i><b>inner1()</b></i> ==> <i><b>Hello Andy</b></i>
      print(ret)
  • 類裝飾器

    • class D(object):
          def __init__(self, a=None):
              self.a = a
              self.mode = "裝飾"
      
          def __call__(self, *args, **kwargs):
              if self.mode == "裝飾":
                  self.func = args[0]  # 默認第一個參數是被裝飾的函數
                  self.mode = "調用"
                  return self
              # 當self.mode == "調用"時,執行下面的代碼(也就是調用使用類裝飾的函數時執行)
              if self.a:
                  print("歡迎來到{}頁面。".format(self.a))
              else:
                  print("歡迎來到首頁。")
              self.func(*args, **kwargs)
      
      
      @D()
      def index(name):
          print("Hello {}.".format(name))
      
      
      @D("電影")
      def movie(name):
          print("Hello {}.".format(name))
      
      if __name__ == '__main__':
          index('張三')
          movie('張三')
  • 裝飾類

    • # 定義一個類裝飾器
      class D(object):
          def __call__(self, cls):
              class Inner(cls):
                  # 重寫被裝飾類的f方法
                  def f(self):
                      print('Hello 張三.')
              return Inner
      
      
      @D()
      class C(object):  # 被裝飾的類
          # 有一個實例方法
          def f(self):
              print("Hello world.")
      
      
      if __name__ == '__main__':
          c = C()
          c.f()
相關文章
相關標籤/搜索