我正在尝试从元类中读取基类变量,以使用以下代码覆盖类变量:
class TypeBaseMeta(type):
def __new__(cls, name, bases, namespace, **kwds):
for base in bases:
namespace['__validators__'] = base['__validators__'] + namespace['__validators__']
return type.__new__(cls, name, bases, namespace, **kwds)
class TypeBase(metaclass=TypeBaseMeta):
__validators__ = ('presence')
def __init__(self, *args, **kwargs):
pass
def validate_presence(self, flag):
if self.data:
return True
class String(TypeBase):
__validators__ = ('length')
def validate_length(self, range):
if len(self.data) in range(*range):
return True
但是我收到了这个错误:
Traceback (most recent call last):
File "types.py", line 18, in <module>
class String(TypeBase):
File "types.py", line 4, in __new__
namespace['__validators__'] = base['__validators__'] + namespace['__validators__']
TypeError: 'TypeBaseMeta' object is not subscriptable
我知道可订阅对象必须有__getitem__()
,并且表现得像字典和列表,但我不知道是什么导致了这个错误。
答案 0 :(得分:1)
__validators__
是超类的属性,而不是dict项,因此应使用base.__validators__
访问它。 (也就是说,将base['__validators__']
更改为base.__validators__
。不要更改namespace['__validators__']
。)
使用namespace['__validators__']
访问当前类的属性的原因是因为该类尚未存在(它由元类创建)。现在你所拥有的只是它属性的一个词。但超类(base
)已经创建,并且是一个真正的类,其属性以正常方式访问,.
。
正如Dunes在评论中指出的那样,您的代码还有另一个问题,即您应该为验证程序编写('presence',)
和('length',)
来创建元组。否则它们只是字符串,子类的__validators__
将被设置为单个字符串'presencelength'
。
答案 1 :(得分:1)
超类中的__validators__
变量无法像字典那样被访问 - 您必须从其__dict__
属性中获取它,或使用getattr
。
- namespace['__validators__'] = base['__validators__'] + namespace['__validators__']
+ namespace['__validators__'] = base.__dict__.get('__validators__', ()) + namespace['__validators__']