装饰器基础二装饰类的装饰器
类可以做装饰器,也可以被装饰器装饰,被装饰器装饰,那这个装饰器可以接收一个类,返回一个类
1、装饰类的装饰器-输入类返回类
def add_str(cls):
def __str__(self):
return str(self.__dict__)
cls.__str__ = __str__
return cls
@add_str
class MyObject:
def __init__(self, a, b):
self.a = a
self.b = b
# 等价形式 MyObject = add_str(MyObject)
o = MyObject(1, 2)
print(type(o))
print(o)
2、先实现普通函数装饰器
def log_func(func):
def wrapper(*args, **kwargs):
print('func start!')
print(f'args: {args}')
res = func(*args, **kwargs)
print('func end!')
return res
return wrapper
@log_func
def fib(n):
if n <= 1:
return 0
return fib(n - 1) + fib(n - 2)
# print(fib(3))
2.1、普通函数装饰器用类包起来, 直接实例化类调用装饰器
class Decorator:
def log_func(self, func):
def wrapper(*args, **kwargs):
print('func start!')
print(f'args: {args}')
res = func(*args, **kwargs)
print('func end!')
return res
return wrapper
d = Decorator()
@d.log_func
def fib(n):
if n <= 1:
return 0
return fib(n - 1) + fib(n - 2)
print(fib(4))
2.2、使用类方法装饰器
class Decorator:
@classmethod
def log_func(cls, func):
def wrapper(*args, **kwargs):
print('func start!')
print(f'args: {args}')
res = func(*args, **kwargs)
print('func end!')
return res
return wrapper
@Decorator.log_func
def fib(n):
if n <= 1:
return 0
return fib(n - 1) + fib(n - 2)
print(fib(4))
2.3、使用静态方法装饰器
class Decorator:
@staticmethod
def log_func(func):
def wrapper(*args, **kwargs):
print('func start!')
print(f'args: {args}')
res = func(*args, **kwargs)
print('func end!')
return res
return wrapper
@Decorator.log_func
def fib(n):
if n <= 1:
return 0
return fib(n - 1) + fib(n - 2)
print(fib(4))
总结:上面实现的是类装饰器给外部函数调用,内部的装饰器函数可以是静态方法,类方法,或者实例方法,那类内部这个装饰器可以给类内部实例方法使用吗?
答案是可以,但是需要像下面这么写。
3、给类方法使用的类装饰器
class Decorator:
# @staticmethod
def log_func(func):
def wrapper(*args, **kwargs):
print('func start!')
print(f'args: {args}')
res = func(*args, **kwargs)
print('func end!')
return res
return wrapper
@log_func
def fib(self, n):
if n <= 1:
return 0
return fib(n - 1) + fib(n - 2)
d = Decorator()
print(d.fib(4))
print('结束')
此时装饰器方法不是实例方法,类方法,静态方法,此时他可以说是类辅助函数装饰器,内部调用没有问题。
但是外部调用就出问题了~
# 外部调用
d = Decorator()
@d.log_func
def f(): # 会报TypeError
pass
外部调用会报TypeError,参数异常。 外部调用时解释器会把类中log_func这个辅助函数当成一个正常实例方法解读,而这个方法中缺少了self,而使用Decorator类的方式外部直接调用则不会报错。此时外部应该使用类直接调用。
@Decorator.log_func
def f(): # 正常输出
pass
4、哪有没有在类中或外部不管通过实例还是类方法均可调用呢,有的,需要在最后一行加如下代码: log_func = staticmethod(log_func) 或者在函数使用@staticmethod修饰成静态方法
class Decorator:
# @staticmethod
def log_func(func):
def wrapper(*args, **kwargs):
print('func start!')
print(f'args: {args}')
res = func(*args, **kwargs)
print('func end!')
return res
return wrapper
@log_func
def fib(self, n):
if n <= 1:
return 0
return fib(n - 1) + fib(n - 2)
log_func = staticmethod(log_func)
# 内部调用
d = Decorator()
print(d.fib(4))
# 对象实例调用
d = Decorator()
@d.log_func
def f(): # 会报TypeError
pass
# 类调用
@Decorator.log_func
def g(): # 正常输出
pass
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)