由类装饰的类的子类

时间:2016-02-11 08:40:34

标签: python decorator

我有一个装饰器,一个装饰器装饰的类和一个子类:

def decorated_by_function(cls):
    return cls

@decorated_by_function
class F(object):
    pass

class G(F):
    pass

没问题。

现在,我将装饰器的实现更改为基于类:

class decorated_by_class(object):
    def __init__(self, cls):
        self._cls = cls

    def __call__(self, *args, **kwargs):
        return self._cls(*args, **kwargs)

@decorated_by_class
class C(object):
    pass

class D(C):
    pass

Python给出了这个错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "h.py", line 23, in <module>
    class D(C):
TypeError: Error when calling the metaclass bases
    __init__() takes exactly 2 arguments (4 given)

编辑:

@donkopotamus在下面给出了部分答案,C是一个实例而不是一个类。这就是为什么C不能被子类化的原因。我明白那个。我的问题是:是否可以保留基于类的方法,同时还允许将装饰类子类化?

使用类的优点是可以扩展。想象一下具有更复杂逻辑的装饰器。什么是修改其某些行为的自然方式,但保留了大部分逻辑?使用基于类的方法使得具有略微不同功能的类似装饰器的树。这就是我想研究这种可能性的原因。

1 个答案:

答案 0 :(得分:0)

在这种情况下

@decorated_by_class
class C(object): 
    pass

大致相当于:

class C(object):
    pass

C = decorated_by_class(C)

因此,在这种情况下,C现在是decorated_by_class的实例 ...它本身不是类。因此,您无法创建从D继承的另一个类C

我相信您可能真正想做的是使用类的实例作为装饰器,例如:

class decorated_by_class(object):
    def __init__(self, *some_decorator_args):
        self.args = some_decorator_args

    def compute_something(self):
        return self.args

    def __call__(self, cls):
        # do something with the class
        cls.decorated_with_args = self.compute_something()
        return cls

@decorated_by_class("hello")
class C(object): 
    pass

print(C.decorated_with_args)    # => ('hello',)

class decorated_by_subclass(decorated_by_class):
    def compute_something(self):
        return self.args * 2

@decorated_by_subclass("hello")
class D(object): 
    pass

print(D.decorated_with_args)    # => ('hello', 'hello')