我想编写类装饰器,对于所有非魔法方法,装饰这些方法。这个想法是所有类的方法在调用之后打印它的名字;我不希望装饰所有的方法,但只有类。装饰者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
"""
答案 0 :(得分:3)
您应该使用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
从未用于装饰,所以它不是装饰者。