Python装饰器
Mar丶流年 人气:01.定义及使用
例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
加载全部内容