【问题标题】:Access base class variable from metaclass从元类访问基类变量
【发布时间】:2014-08-06 20:27:16
【问题描述】:

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

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__() 并且表现得像字典和列表,但我不知道是什么导致了这个错误。

【问题讨论】:

  • 您的验证器是字符串,而不是字符串元组。单个元素元组指定为(item,)

标签: python python-3.x metaprogramming


【解决方案1】:

__validators__ 是超类的属性,而不是字典项,所以应该使用base.__validators__ 访问它。 (即把base['__validators__']改成base.__validators__,不要改namespace['__validators__']。)

您使用namespace['__validators__'] 访问current 类的属性的原因是该类还不存在(它是由元类创建的)。现在你所拥有的只是它的属性。但是超类 (base) 已经创建,并且是一个真正的类,其属性可以通过. 以正常方式访问。

正如 Dunes 在评论中指出的那样,您的代码还有另一个问题,即您应该为验证器编写 ('presence',)('length',) 来创建元组。否则它们只是字符串,子类的__validators__ 将被设置为单个字符串'presencelength'

【讨论】:

  • 当我将namespace['__validators__'] 更改为base.__validators__ 时,我得到了KeyError: '__validators__'
  • @RalphGutkowski:不要改变namespace['__validators__']。更改base['__validators__']。 (我在回答中添加了说明。)
  • 抱歉造成误会。我犯了一个错误。我更改了base['__validators__'],但仍然出现同样的错误。全线:namespace['__validators__'] = base.__validators__ + namespace['__validators__']
  • @RalphGutkowski:我无法重现。当我使用我建议的更改运行您的代码时,它可以正常工作。见this ideone example
  • 我的错。在我的文件末尾,我有一个从没有 __validators__ 变量的 TypeBase 扩展的类。谢谢你的帮助。我会给你另一个 +1 以获得你写的完美解释!
【解决方案2】:

超类中的 __validators__ 变量不能像字典一样访问 - 您必须从它的 __dict__ 属性中获取它,或者使用 getattr

- namespace['__validators__'] = base['__validators__'] + namespace['__validators__']
+  namespace['__validators__'] = base.__dict__.get('__validators__', ()) + namespace['__validators__']

【讨论】:

    猜你喜欢
    • 2013-01-16
    • 2021-05-05
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 2014-08-22
    • 1970-01-01
    相关资源
    最近更新 更多