python中的装饰器decorator(中)
作者:互联网
在上文中,我们讨论了用于修饰function的装饰器,现在我们来看用于修饰class的装饰器。首先来看一个例子,其中使用了built-in的@property @classmethod @staticmethod。@property常用于设置setter和getter。
class Student:
def __init__(self, name,id):
self._name = name
self._id = id
@property
def id(self):
return self._id
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if value.isalpha():
self._name = value
@classmethod
def tom(cls):
return Student("tom",0)
@staticmethod
def identity():
return "student"
在使用时,如下所示调用property修饰的方法。
>>> jack = Student("jack",1)
>>> jack.name
'jack'
>>> jack.id
1
>>> jack.name = "Jack Tony"
>>> jack.name
'jack'
>>> jack.id=2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
@classmethod vs @static method
1.class method第一个参数为cls,且能够获取类内部状态,通常作为一个工厂方法,返回这个类的一个对象。
2.static method仅仅为一个工具方法,不能获得类内部状态,只根据参数决定行为。
修饰类中的方法和修饰一个函数时一样的,自己定义的装饰器也可使用。另一种方式是装饰整个类
修饰整个类
我们在上文为函数写的装饰器都可以作用到类上,不过实际上等同于其作用到了类的__init__方法上。
多个decorator
函数有多个decorator,会按顺序执行。如下:
def do_twice(func):
def do_twice_wrapper(*args,**kwargs):
func(*args,**kwargs)
return func(*args,**kwargs)
return do_twice_wrapper
def debug(func):
def debug_wrapper(*args,**kwargs):
args_repr = [repr(a) for a in args]
kwargs_repr = [f"{k}={v!r}"for k,v in kwargs.items() ]
signature = ",".join(args_repr+kwargs_repr)
print(f"calling {func.__name__}({signature})")
value = func(*args,**kwargs)
print(f"{func.__name__} returned {value}")
return value
return debug_wrapper
@do_twice
@debug
def greet(name):
print(f"hello {name}")
greet("tom")
# 先@debug再@do_twice
calling greet('tom')
hello tom
greet returned None
calling greet('tom')
hello tom
greet returned None
使用带参数的decorator
比如我们要将@do_twice扩展为执行某一函数任意次数。
import functools
def repeat(num_times):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args,**kwargs):
for _ in range(num_times-1):
func(*args,**kwargs)
return func(*args,**kwargs)
return wrapper_repeat
return decorator_repeat
@repeat(num_times=4)
def greet(name):
print(f"hello {name}")
改进装饰器
我们可以改进装饰器,使其既可以接受参数,也可以不接受
def repeat(_func=None,*,num_times=2):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args,**kwargs):
for _ in range(num_times-1):
func(*args,**kwargs)
return func(*args,**kwargs)
return wrapper_repeat
if _func is None:
return decorator_repeat
else:
return decorator_repeat(_func)
@repeat
def greet(name):
print(f"hello {name}")
#等同于,repeat参数中,_func有值
greet = repeat(greet)
@repeat(num_times=4)
def greet(name):
print(f"hello {name}")
#等同于,repeat参数中,作为positional arguments或keywords arguments的_func没有值
tmp = repeat(num_times=4)
@tmp
def greet(name):
print(f"hello {name}")
参考
- https://www.geeksforgeeks.org/class-method-vs-static-method-python/#:~:text=A class method takes cls,nothing about the class state.
- https://realpython.com/primer-on-python-decorators/#functions
标签:repeat,return,name,python,decorator,func,kwargs,装饰,def 来源: https://www.cnblogs.com/pitaya01/p/16372374.html