好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Python的装饰器详情介绍

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装饰器内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

查看更多关于Python的装饰器详情介绍的详细内容...

  阅读:44次