Mat*_*ann 5 python python-3.x python-decorators
我正在尝试装饰类中的所有方法,并且我使用此代码成功,但我也试图将调用记录到运算符* + - /,有没有办法装饰它们或类似getattr(self,"*")记录调用的东西?
class Logger(object):
def __init__(self, bool):
self.bool = bool
def __call__(self, cls):
class DecoratedClass(cls):
def __init__(cls, *args, **kwargs):
super().__init__(*args, **kwargs)
if not(self.bool):
return
methods = [func for func in dir(cls)
if callable(getattr(cls, func))
and not func.startswith("__class")]
for func in methods:
old_func = getattr(cls, func)
def decorated_function(fname, fn):
def loggedFunction(*args, **kwargs):
print("Calling {0} from {3} with params {1} and kwargs {2}".format(fname.upper(), args, kwargs, cls))
return fn(*args, **kwargs)
return loggedFunction
setattr(cls, func, decorated_function(func, old_func))
return DecoratedClass
Run Code Online (Sandbox Code Playgroud)
@Logger(True)
class DummyClass():
def __init__(self,foo):
self.foo = foo
def bar(self):
print(self.foo)
def __mul__(self,other):
print("Hello",other)
if __name__ == '__main__':
a = DummyClass('hola')
a.method()
a.__mul__(a) #this is logged
print(a*a) #this is not logged by decorator
Run Code Online (Sandbox Code Playgroud)
感谢 \xc5\x81ukasz,这是一个工作脚本。
\n\n我遇到的一个困难是处理多个实例并避免多次修饰相同的类方法。为了解决这个问题,我跟踪装饰类方法(cls.__logged )。
另一个困难是处理像__setattr__, __getattribute__, __repr__, ... 这样的神奇方法,我的解决方案是忽略它们,除了必须在开始时定义的列表(loggable_magic_methods。
from functools import wraps\n\n\nloggable_magic_methods = ['__mul__',]\n\n\ndef is_magic_method(method):\n return method.startswith('__')\n\n\nclass Logger(object):\n def __init__(self, bool):\n self.bool = bool\n\n def __call__(self, cls):\n\n class LoggedClass(cls):\n cls.__logged = []\n def __init__(instance, *args, **kwargs):\n super().__init__(*args, **kwargs)\n\n if not(self.bool):\n return\n\n methods = [funcname for funcname in dir(instance)\n if callable(getattr(instance, funcname))\n and (funcname in loggable_magic_methods or not is_magic_method(funcname))]\n\n def logged(method):\n @wraps(method)\n def wrapper(*args, **kwargs):\n print (method.__name__, args, kwargs, cls)\n return method(*args, **kwargs)\n return wrapper\n\n for funcname in methods:\n if funcname in cls.__logged:\n continue\n\n if is_magic_method(funcname):\n setattr(cls, funcname, logged(getattr(cls, funcname)))\n cls.__logged.append(funcname)\n else:\n setattr(instance, funcname, logged(getattr(instance, funcname)))\n return LoggedClass\n\n@Logger(True)\nclass DummyClass():\n def __init__(self, foo, coef):\n self.foo = foo\n self.coef = coef\n def bar(self):\n print(self.foo)\n def __mul__(self, other):\n print(self.foo)\n print(other.foo)\n return self.coef * other.coef\n\nif __name__ == '__main__':\n a = DummyClass('hola', 1)\n a.bar()\n print()\n print(a.__mul__(a))\n print()\n print(a*a)\n print()\n b = DummyClass('gracias', 2)\n b.bar()\n print()\n print(b.__mul__(a))\n print()\n print(b*a)\nRun Code Online (Sandbox Code Playgroud)\n