Inheriting from decorated classes
我想用另一个班级装饰一个班级。我还想从装饰类继承,但我得到了一些错误。以下是我的代码:
1 2 3 4 5 6 7 8 9 10 | class Decorator: def __init__(self, decorated): pass @Decorator class Foo: pass class Goo(Foo): pass |
当我尝试从
Traceback (most recent call last):
File"test.py", line 9, in
class Goo(Foo):
TypeError: __init__() takes exactly 2 positional arguments (4 given)
通过向
1 2 3 | def __init__(self, *args): for arg in args: print(arg) |
…我得到以下输出:
Goo
(<__main__.Decorator object at 0x010073B0>,)
{'__module__': '__main__'}
这些参数是什么?我应该如何在
我将尝试回答"那些参数是什么"问题。此代码:
1 2 3 | @Decorator class Foo: pass |
相当于:
1 2 3 | class Foo: pass Foo = Decorator(Foo) |
这意味着
当您试图使用这个实例作为类(
这就是你如何在
有关这方面的更多信息,请参见:http://www.python.org/download/releases/2.2.3/descrintro/元类(尤其是"执行类语句时……"部分)
在类被定义之后,您是否试图向类添加一个mixin?如果是这样,你可以用这种方式注入混合物:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def inject_class(mixin): def _inject_class(cls): return type(cls.__name__,(mixin,)+cls.__bases__,dict(cls.__dict__)) return _inject_class class MixIn(object): def mix(self): print('mix') @inject_class(MixIn) class Foo(object): def foo(self): print('foo') class Goo(Foo): def goo(self): print('goo') goo=Goo() goo.mix() goo.foo() goo.goo() |
印刷品
1 2 3 | mix foo goo |
如果您不想使用
1 2 3 4 5 6 7 8 9 10 | def decorate(cls): class Decorator(object): def deco(self): print('deco') return type(cls.__name__,(Decorator,)+cls.__bases__,dict(cls.__dict__)) @decorate class Foo(object): def foo(self): print('foo') |
结果是一样的。
我也遇到了同样的问题,下面的解决方案对我有效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | from functools import update_wrapper class decoratorBase(): def __new__(cls, logic): self = object.__new__(cls) self.__init__(logic) def new (cls): #cls is the decorated class type, not the decorator class type itself self._createInstance(cls) self._postInstanceCreation() return self self._logic.__new__ = new #return the wrapped class and not a wrapper return self._logic def __init__(self, logic): #logic is the decorated class self._logic = logic def _createInstance(self, cls): self._logicInstance = object.__new__(cls) self._logicInstance.__init__() def _postInstanceCreation(self): pass class factory(decoratorBase): def __init__(self, *largs, **kwargs): super().__init__(*largs, **kwargs) self.__instance = None def _createInstance(self, cls): self._logicInstance = None self._cls = cls def _postInstanceCreation(self): update_wrapper(self, self._cls) def __call__(self, userData, *largs, **kwargs): logicInstance = object.__new__(self._cls) logicInstance.__init__(*largs, **kwargs) logicInstance._update(userData) return logicInstance class singelton(decoratorBase): def _postInstanceCreation(self): update_wrapper(self, self._logicInstance) def __call__(self, userData): self._logicInstance._update(userData) return self._logicInstance class base(): def __init__(self): self.var = 0 print ("Create new object") def __call__(self): self.var += self._updateValue() def _update(self, userData): print ("Update object static value with {0}".format(userData)) self.var = userData @factory class factoryTestBase(base): def __call__(self): super().__call__() print("I'm a factory, here is the proof: {0}".format(self.var)) def _updateValue(self): return 1 class factoryTestDerived(factoryTestBase): def _updateValue(self): return 5 @singelton class singeltonTestBase(base): def __call__(self): super().__call__() print("I'm a singelton, here is the proof: {0}".format(self.var)) def _updateValue(self): return 1 class singeltonTestDerived(singeltonTestBase): def _updateValue(self): return 5 |
这种方法的魔力在于对
1 2 3 4 5 | def new (cls): self._createInstance(cls) self._postInstanceCreation() return self self._logic.__new__ = new |
使用它,您可以在从装饰类创建对象的过程中访问装饰器方法,如
现在让我们运行一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | >>> factoryObjCreater = factoryTestBase() >>> factoryObj1 = factoryObjCreater(userData = 1) Create new object Update object static value with 1 >>> factoryObj2 = factoryObjCreater(userData = 1) Create new object Update object static value with 1 >>> factoryObj1() I'm a factory, here is the proof: 2 >>> factoryObj2() I'm a factory, here is the proof: 2 >>> factoryObjDerivedCreater = factoryTestDerived() >>> factoryObjDerived1 = factoryObjDerivedCreater(userData = 2) Create new object Update object static value with 2 >>> factoryObjDerived2 = factoryObjDerivedCreater(userData = 2) Create new object Update object static value with 2 >>> factoryObjDerived1() I'm a factory, here is the proof: 7 >>> factoryObjDerived2() I'm a factory, here is the proof: 7 >>> singeltonObjCreater = singeltonTestBase() Create new object >>> singeltonObj1 = singeltonObjCreater(userData = 1) Update object static value with 1 >>> singeltonObj2 = singeltonObjCreater(userData = 1) Update object static value with 1 >>> singeltonObj1() I'm a singelton, here is the proof: 2 >>> singeltonObj2() I'm a singelton, here is the proof: 3 >>> singeltonObjDerivedCreater = singeltonTestDerived() Create new object >>> singeltonObjDerived1 = singeltonObjDerivedCreater(userData = 2) Update object static value with 2 >>> singeltonObjDerived2 = singeltonObjDerivedCreater(userData = 2) Update object static value with 2 >>> singeltonObjDerived1() I'm a singelton, here is the proof: 7 >>> singeltonObjDerived2() I'm a singelton, here is the proof: 12 >>> |