【问题标题】:Subclassing a decorated class子类化装饰类
【发布时间】:2015-03-21 01:10:49
【问题描述】:

你会如何子类化一个装饰类?这是一些代码,我想我一定错过了一些非常简单的东西

def decorator_with_args(*args, **kwargs):
    def decorator(cls):
        def wrapper(*wargs, **wkwargs):
            print("wargs", wargs, wkwargs)
            return cls(*wargs, **wkwargs)

        return wrapper

    return decorator


@decorator_with_args()
class MyClass(object):
    def __init__(self, *args, **kwargs):
        print("args", args, kwargs)


class MySubClass(MyClass):
    pass


myClass = MyClass("arg", kwarg="kwarg")

这将在编译时引发TypeError

Traceback (most recent call last):
  File "/path/to/file", line 46, in <module>
    class MySubClass(MyClass):
TypeError: function() argument 1 must be code, not str

【问题讨论】:

  • @AshwiniChaudhary 3.4
  • 您在这里的预期行为是什么?您是否希望每次初始化 MySubClass 的子类时都调用 print("wargs", wargs, wkwargs)?
  • 对于函数functools.wraps用于将实际函数赋值给装饰器的__wrapped__属性,你可以做类似的事情:wrapper.__wrapped__ = cls然后使用class MySubClass(getattr(MyClass, '__wrapped__', MyClass)):。

标签: python subclass decorator metaclass


【解决方案1】:

你的装饰器错了。它应该返回一个类而不是一个函数。

def decorator_with_args(*args, **kwargs):
    def decorator(cls):
        class Wrapper(cls):
            def __init__(self, *wargs, **wkwargs):
                print(wargs, wkwargs)

        return Wrapper

    return decorator

【讨论】:

  • 谢谢,但看起来错误是在调用包装器之前引发的
  • 好吧,我以前的答案版本不太准确(已编辑)。您根本不应该有 wrapper 函数-在您的情况下,子类扮演包装器的角色。 wrapped 没有被调用,因为它应该是一个类,但它是一个函数。
  • 感谢您的帮助 Bartosz,但是您的更新版本不会有任何好处,仍然会引发错误。我提供的代码是存在wrapper 的项目的简化版本
  • 那我觉得子类化没有什么好办法。看起来你的装饰器没有返回一个类,而是一个伪装成一个类的函数(如果你调用它,你会得到一个实例)。但是返回实例的函数不允许您以一种很好的方式创建子类(好吧,您可以这样做class MySubClass(type(MyClass())),但它显然很糟糕)。
  • 好的,就像我想的那样简单 :) 我猜wrapper 应该是一个类而不是一个函数。我会用一个工作版本更新你的答案,并接受它为我指明正确的方向。
猜你喜欢
  • 1970-01-01
  • 2010-12-23
  • 2013-05-23
  • 2019-07-23
  • 2014-01-14
  • 2018-07-27
  • 1970-01-01
  • 2018-04-28
  • 1970-01-01
相关资源
最近更新 更多