修饰所有方法的类的装饰器
问题描述:
我想写所有非魔法方法的类修饰器来装饰这些方法。这个想法是,所有类的方法在打电话后打印它的名字;我不想装饰所有的方法,但只有阶级。装饰者log_method
的作品。我有问题log_class
装饰。没有错误,也没有输出。修饰所有方法的类的装饰器
import traceback
import inspect
def log_method(func):
def inner(*args, **kwargs):
print("{}{}".format(int(len(traceback.extract_stack())/2) * " ", func.__name__))
return func(*args, **kwargs)
return inner
def log_class(cls):
for m in dir(cls):
if not m.startswith("__") and inspect.isfunction(getattr(cls, m)):
m = log_method(m)
print(m)
return cls
@log_class
class Cls:
def __init__(self):
pass
def A(self):
self.B()
def B(self):
self.C()
def C(self):
pass
Cls().A()
"""
Excepted output:
A
B
C
"""
答
你应该重新绑定方法使用setattr
传递方法的名称m
类对象;像你所做的那样分配给当地名称m
,什么都不做。
更进一步说,您目前正在将一个字符串m
传递给log_method
。相反,你应该通过getattr
取回后传递给函数对象本身:
def log_method(func):
def inner(*args, **kwargs):
print("{}{}".format(int(len(traceback.extract_stack())/2) * " ", func.__name__))
return func(*args, **kwargs)
return inner
def log_class(cls):
for m in dir(cls):
if not m.startswith("__") and inspect.isfunction(getattr(cls, m)):
setattr(cls, m, log_method(getattr(cls, m))) # here
return cls
Cls.A()
# A
# B
# C
PS:log_method
从不用于装饰,所以它不是一个装饰。
+1
不错。现在用元类来做。 ;) –
+0
@ PM2Ring抛出一个元类,并且答案变成一个漩涡,如果OP没有以前的经验,那么更有可能是这样:) –
'm = log_method(m)'只是给变量'm'赋值'log_method'的返回值,它根本不影响类。 –