从元类访问基类变量
我正在尝试通过这个代码,从元类中读取基类的变量,以便覆盖类的变量:
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__()
方法,并且要像字典和列表那样工作,但我不知道是什么导致了这个错误。
2 个回答
2
在父类中,__validators__
这个变量不能像字典那样直接访问。你需要通过它的 __dict__
属性来获取,或者使用 getattr
函数。
- namespace['__validators__'] = base['__validators__'] + namespace['__validators__']
+ namespace['__validators__'] = base.__dict__.get('__validators__', ()) + namespace['__validators__']
2
__validators__
是父类的一个属性,不是字典里的一个项,所以你应该用 base.__validators__
来访问它。也就是说,把 base['__validators__']
改成 base.__validators__
。而 namespace['__validators__']
别改。
你用 namespace['__validators__']
来访问当前类的属性,是因为这个类还没创建出来(它正在被元类创建中)。现在你手里只有一个它属性的字典而已。但是父类(base
)已经创建好了,是一个真实的类,你可以用正常的方式通过 .
来访问它的属性。
正如 Dunes 在评论中提到的,你的代码还有另一个问题,就是你应该写 ('presence',)
和 ('length',)
来定义你的验证器,这样才能创建元组。否则它们只是字符串,这样子类的 __validators__
就会被设置成单个字符串 'presencelength'
。