首頁 > 軟體

Python的裝飾器詳情介紹

2022-03-01 13:03:35

1.定義及使用

例1:裝飾器定義:

      def 裝飾器函數(外部函數):
            def 行內函式(*args,**kwargs):
                ...前置裝飾...
                外部函數(*args,**kwargs)
                ...後置裝飾...
            return 行內函式

 例2:裝飾器兩種呼叫方式

  •  第一種:裝飾器函數(外部函數)(引數1,引數2......)
  •  第二種:定義時通過 @裝飾器函數名 繫結 外部函數(外部函數呼叫時觸發)
# coding:utf-8:

if __name__ == '__main__':

    # 例1 裝飾器定義
    # 裝飾器函數 外部函數func
    def decorator(func):

        # 行內函式 進行裝飾
        # *args 將 引數1,引數2...... 變為 (引數1,引數2.......)
        # **kwargs 將 引數3=引數值3,引數4=引數值4...... 變為 {'引數3':引數值3,'引數4':'引數值4'......}
        # *args,**kwargs 將 引數1,引數2......引數3=引數值3,引數4=引數值4...... 變為 (引數1,引數2.......),{'引數3':引數值3,'引數4':'引數值4'......}
        def inline(*args, **kwargs):
            # *args,**kwargs 將引數還原
            # 將 (引數1,引數2.......),{'引數3':引數值3,'引數4':'引數值4'......} 變為 引數1,引數2......引數3=引數值3,引數4=引數值4......
            name = func(*args, **kwargs)
            print(f'name is {name}')

        # return 行內函式
        return inline

    def talk(name):
        return name

    # 例2 裝飾器的兩種呼叫方式
    # 第一種 裝飾器函數(外部函數)(引數1,引數2......)
    decorator(talk)('xie')  # name is xie

    # 第二種 @裝飾器函數名 繫結 外部函數
    @decorator
    def see(name):
        return name
    # 呼叫時觸發裝飾器
    see('xie')  # name is xie

2.@classmethod

  •   1.被@classmethod裝飾的類方法可以通過class.方法(引數1,引數2......)呼叫
  •     2.但是定義函數時 self 需要變成 cls
  •     3.其內部不能呼叫類的普通方法(無裝飾器修飾的方法),可以呼叫@classmethod,@staticmethod裝飾的方法
  •     4.能存取類的屬性 
  •     5.普通類中能通過self呼叫@classmethod裝飾的方法
# coding:utf-8:

if __name__ == '__main__':


    class A(object):
        __name = 'python'

        # 普通方法
        def talk(self):
            print(self.__name)
            # self.see() 普通類中能通過self呼叫@classmethod裝飾的方法

        # 被@classmethod裝飾的類方法可以通過class.方法(引數1,引數2......)呼叫
        # 但是定義函數時 self 需要變成 cls
        @classmethod
        def see(cls, description='good'):
            # cls.talk() Error 不能呼叫類的普通方法(非@classmethod,@staticmethod修飾的方法)
            # cls.look() 可以呼叫@classmethod裝飾的方法
            # cls.jump() 可以呼叫@staticmethod裝飾的方法
            # 能存取類的屬性
            print(f'{cls .__name} is {description}')

        @classmethod
        def look(cls):
            print(f'I like {cls.__name}')

        @staticmethod
        def jump():
            print(f'I am jump')

    a = A()
    a.talk()  # python
    # A.talk() Error 不能通過class.方法(引數1,引數2......)呼叫
    a.see()  # python is good

    # 通過class.方法(引數1,引數2......)呼叫
    A.see()  # python is good

@staticmethod

  •    1. 被@staticmethod裝飾的類方法可以通過class.方法(引數1,引數2......)呼叫
  •     2. 但是定義函數時 無須self和cls
  •     3. 由於其無self,cls註定其無法存取類屬性&呼叫類方法
  •     4. 在類的普通方法中可以通過self呼叫@staticmethod裝飾的方法
# coding:utf-8:

if __name__ == '__main__':
    '''
      '''

    class B(object):
        __name = 'php'

        def talk(self):
            # 可以通過self呼叫@staticmethod裝飾的方法
            self.see(self.__name)

        # 無須self,cls
        @staticmethod
        def see(description='good'):
            print(f'description is {description}')


    B.see()  # description is good
    B.see('ok')  # description is ok
    B().talk()  # description is php

@property

  • 1.@property裝飾的函數被用來代替類中與函數名相同的屬性

      定義: @property
            def 屬性名(self):
                .......

  •   2.被@property裝飾器代替的屬性,無法通過object.屬性名=屬性值進行賦值(除非使用了@屬性名.setter裝飾器):

      定義: @屬性名.setter
            def 屬性名(self,屬性值):
                ......  

  • 3.被@property修飾的函數不能在外部通過object.函數名()呼叫,只能object.函數名 當做屬性
  • 4.只有被@property代替了的屬性才能使用@屬性名.setter 裝飾器
  • 5. __setattr__ 的優先順序高於 @屬性名.setter裝飾器的優先順序
# coding:utf-8:

if __name__ == '__main__':
    '''
   
    '''
    class A(object):
        __name = 'python'
        sex = 'man'

        # 不能設定成私有
        # @property裝飾的函數被用來代替類中與函數名相同的屬性
        # 這個代替了name屬性
        @property
        def name(self):
            return self.__name

@property

def sex(self):
            return 'woman'

        # 解決被替代屬性的 object.屬性=屬性值 賦值問題
        # 配合@property裝飾器使用,只有被@property代替了的屬性才能使用@屬性名.setter 裝飾器
        @name.setter
        def name(self, value):
            print(f'value is {value}')

        # __setattr__ 的優先順序高於 @屬性名.setter裝飾器的優先順序
        # def __setattr__(self, key, value):
        #     print(f'key is {key}, value is {value}')


    a = A()
    print(a.name)  # python
    # print(a.name()) Error 被@property修飾的函數不能在外部通過object.函數名()呼叫,只能object.函數名 當做屬性

    # 被@property代替了
    print(a.sex)  # 是 woman 不是 man

    # a.sex = 'man' Error 被代替的屬性,不能通過object.屬性名 = 屬性值 進行賦值,除非有@屬性名.setter裝飾
    a.name = 'python3.7'  # value is python3.7

到此這篇關於Python的裝飾器詳情介紹的文章就介紹到這了,更多相關Python裝飾器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com