装饰运算符python3.5

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)

Fro*_*don 2

感谢 \xc5\x81ukasz,这是一个工作脚本。

\n\n

我遇到的一个困难是处理多个实例并避免多次修饰相同的类方法。为了解决这个问题,我跟踪装饰类方法(cls.__logged )。

\n\n

另一个困难是处理像__setattr__, __getattribute__, __repr__, ... 这样的神奇方法,我的解决方案是忽略它们,除了必须在开始时定义的列表(loggable_magic_methods

\n\n
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)\n
Run Code Online (Sandbox Code Playgroud)\n