我有一些具有一些并行属性的子类,并且我想使用装饰器模式来处理,以便可以使用简单的isinstance
语法简单地构建不同的图形。我提到了这个post。
我的测试代码(Py27)如下:
import inspect
class Cls_Base(object):
def __init__(self, n):
self.number = n
def __str__(self):
return '{}, {}'.format(self.number,self.__class__.__name__)
class Ext_c1(Cls_Base):
def __init__(self):
self.pos=self.number+3
def __str__(self):
return '{}, {}'.format(self.pos,self.__class__.__name__)
class Ext_c2(Cls_Base):
def __init__(self):
pass
def __str__(self):
return '{}, {}'.format(self.number+1,self.__class__.__name__)
class Cls_Decorator(Cls_Base):
def __new__(cls, decoratee, c):
cls_name=c if inspect.isclass(c) else globals()[c]
cls = type(cls_name.__name__,
(cls_name, decoratee.__class__),
decoratee.__dict__)
return object.__new__(cls)
base=Cls_Base(1)
c1=Cls_Decorator(base,Ext_c1)
c1_2=Cls_Decorator(c1,Ext_c2)
c2=Cls_Decorator(base,Ext_c2)
在检查c1,c1_2,c2的值和方法时,结果变为:
>>> base.__dict__
{'number': 1}
>>> c1.__dict__
{}
>>> c2.__dict__
{}
>>> c1_2.__dict__
{}
>>> str(c1)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "test_cls.py", line 17, in __str__
return '{}, {}'.format(self.pos,self.__class__.__name__)
AttributeError: 'Ext_c1' object has no attribute 'pos'
>>> str(c2)
'2, Ext_c2'
>>> str(base)
'1, Cls_Base'
>>> str(c1_2)
'2, Ext_c2'
>>> c1.__init__()
>>> str(c1)
'4, Ext_c1'
>>> c1.__dict__()
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: 'dict' object is not callable
>>> c1.__dict__
{'pos': 4}
看,重载和继承的方法运行良好。但是装饰器无法初始化类dict,因为在分配新空间之前没有调用任何发起器。我应该怎么做才能避免在课堂外显式使用__init__()
?还是有一些更优雅的方式来完成同等工作?
附加问题:使用inspect.getmro
可能会导致另一个问题,即下面的两个Ext_c1
不是同一个人。
>>> inspect.getmro(type(c1))
(<class '__main__.Ext_c1'>, <class '__main__.Ext_c1'>,
<class '__main__.Cls_Base'>, <type 'object'>)