Python-类装饰器-运行时继承

Python-类装饰器-运行时继承,python,class,python-decorators,Python,Class,Python Decorators,我正在尝试创建一个decorator,它将向包装类\uuuu init\uuuu方法注入一些功能。这就是有效的方法 class Decorator: def __init__(self, arg): print(arg) self.arg = arg def __call__(self, cls): print(cls) class Wrapped(cls): def __init__(s

我正在尝试创建一个decorator,它将向包装类
\uuuu init\uuuu
方法注入一些功能。这就是有效的方法

class Decorator:
    def __init__(self, arg):
        print(arg)
        self.arg = arg

    def __call__(self, cls):
        print(cls)

        class Wrapped(cls):
            def __init__(self, first_arg, second_arg, **kwargs):
                cls.__init__(self, first_arg, second_arg, **kwargs)
                print('in wrapped init', self.variable)

        return Wrapped


@Decorator('random_string')
class TestClass:
    def __init__(self, first_arg, second_arg, **kwargs):
        self.variable = 10
        print('TestClass init')


test = TestClass(first_arg='one', second_arg='two')
生产

random_string
<class '__main__.TestClass'>
TestClass init
in wrapped init 10
输出:

Traceback (most recent call last):
  File "/home/python_examples/test_decorators.py", line 24, in <module>
    test = TestClass(first_arg='one', second_arg='two')
<class '__main__.TestClass'>
TypeError: __call__() got an unexpected keyword argument 'first_arg'
回溯(最近一次呼叫最后一次):
文件“/home/python\u examples/test\u decorators.py”,第24行,在
test=TestClass(第一个参数为一,第二个参数为二)
TypeError:\uuuuu call\uuuuuuuuu()获得意外的关键字参数“first\u arg”
两个问题:

  • 这是一种众所周知且有效的装饰类方法吗
  • 为什么从未使用过的“随机字符串”参数至关重要

    • 这是因为您的decorator类将
      arg
      作为构造函数参数。因此,当您删除decorator参数时,请确保您也从
      \uuuu init\uuu
      方法中删除了该参数。改变这个

      class Decorator:
          def __init__(self, arg):
              print(arg)
              self.arg = arg
      
          def __call__(self, cls):
              print(cls)
      
              class Wrapped(cls):
                  def __init__(self, first_arg, second_arg, **kwargs):
                      cls.__init__(self, first_arg, second_arg, **kwargs)
                      print('in wrapped init', self.variable)
      
              return Wrapped
      
      对此

      class Decorator:
          def __init__(self):
              pass
      
          def __call__(self, cls):
              print(cls)
      
              class Wrapped(cls):
                  def __init__(self, first_arg, second_arg, **kwargs):
                      cls.__init__(self, first_arg, second_arg, **kwargs)
                      print('in wrapped init', self.variable)
      
              return Wrapped
      

      将解决您的问题。

      这是因为您的decorator类将
      arg
      作为构造函数参数。因此,当您删除decorator参数时,请确保您也从
      \uuuu init\uuu
      方法中删除了该参数。改变这个

      class Decorator:
          def __init__(self, arg):
              print(arg)
              self.arg = arg
      
          def __call__(self, cls):
              print(cls)
      
              class Wrapped(cls):
                  def __init__(self, first_arg, second_arg, **kwargs):
                      cls.__init__(self, first_arg, second_arg, **kwargs)
                      print('in wrapped init', self.variable)
      
              return Wrapped
      
      对此

      class Decorator:
          def __init__(self):
              pass
      
          def __call__(self, cls):
              print(cls)
      
              class Wrapped(cls):
                  def __init__(self, first_arg, second_arg, **kwargs):
                      cls.__init__(self, first_arg, second_arg, **kwargs)
                      print('in wrapped init', self.variable)
      
              return Wrapped
      

      将解决您的问题。

      实际上,它是这样工作的:

      # Assume you have a decorator class and a class named A which is needed to decorate.
      
      @Decorator
      class A:
          ...
      
      # is the same as 
      
      class A:
          ...
      
      A = Decorator()(A)
      
      这就是为什么您需要定义
      \uuuuu-cal\uuuu

      在这里您可以看到,如果您的
      装饰程序
      接受一些参数进行初始化,您需要使用类似
      A=Decorator(xxx)(A)
      的东西。而decorator语法中的等效项是:

      @Decorator(xxx)
      class A:
          ...
      

      实际上,这就是它的工作原理:

      # Assume you have a decorator class and a class named A which is needed to decorate.
      
      @Decorator
      class A:
          ...
      
      # is the same as 
      
      class A:
          ...
      
      A = Decorator()(A)
      
      这就是为什么您需要定义
      \uuuuu-cal\uuuu

      在这里您可以看到,如果您的
      装饰程序
      接受一些参数进行初始化,您需要使用类似
      A=Decorator(xxx)(A)
      的东西。而decorator语法中的等效项是:

      @Decorator(xxx)
      class A:
          ...
      

      它不起作用。回溯(最后一次调用):文件“/home/python\u examples/test\u decorators.py”,第16行,在@Decorator TypeError:\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()接受1个位置参数,但有2个位置参数。像这样调用Decorator
      而不是像这样调用
      Decorator
      这两种?在使用@annotation时,我从不需要实例化decorator。我的意思是,使用@like
      @decorator()
      调用decorator。如果是函数,则无需添加括号。因为它是一个类,我们需要添加括号。所谓“因为它是一个类,我们需要添加括号”,你是指装饰器本身还是它装饰的类(在本例中为TestClass)?它不起作用。回溯(最后一次调用):文件“/home/python\u examples/test\u decorators.py”,第16行,在@Decorator TypeError:\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()接受1个位置参数,但有2个位置参数。像这样调用Decorator
      而不是像这样调用
      Decorator
      这两种?在使用@annotation时,我从不需要实例化decorator。我的意思是,使用@like
      @decorator()
      调用decorator。如果是函数,则无需添加括号。因为它是一个类,所以我们需要添加括号。这里的“因为它是一个类,所以我们需要添加括号”是指装饰器本身还是它装饰的类(在本例中为TestClass)?