从元类访问基类变量

时间:2014-08-06 20:27:17

标签: python python-3.x metaprogramming

我正在尝试从元类中读取基类变量,以使用以下代码覆盖类变量:

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 个答案:

答案 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__']