【问题标题】:Why does a metaclass not have access to the attributes inhereited from a subclass of a class defined by the metaclass?为什么元类不能访问由元类定义的类的子类继承的属性?
【发布时间】:2015-07-06 16:40:59
【问题描述】:

Foo 使用元类 Meta 定义。元类循环遍历类属性并将它们打印到屏幕上。

Bar 子类Foo。但是,元类不会打印从 Bar 继承的属性。

为什么元类不能访问FooBar 中继承的属性?我对 python 的元类系统有什么不了解的地方?

这是2.7中的示例代码:

class Meta(type):
    def __init__(cls, name, bases, attrs):
        print "bases = {}".format(bases)
        items = {k:v for k,v in attrs.iteritems() if not k.startswith('__')}
        for k,v in items.iteritems():
            print k, v

class Foo(object):
    __metaclass__ = Meta
    hi = 1

# This prints:
# bases = (<type 'object'>,)
# hi 1

class Bar(Foo):
    pass

# This prints:
# bases = (<class '__main__.Foo'>,)

Foo.hi
#prints 1
Bar.hi
#prints 1

【问题讨论】:

    标签: python python-2.7 inheritance metaclass


    【解决方案1】:

    __init__attrs 参数仅包含 该类 的属性,而不包含其基类的属性。

    Bar 对象没有hi 属性。相反,当您请求Bar.hi 时,查找将从Bar 开始,发现它没有hi,然后在基础Foo 中查找它。

    【讨论】:

      【解决方案2】:

      正如@orlp 所说,attrs 仅包含正在创建的类的类字典。但是,您仍然可以访问hi,因为它位于Foo 的基础之一的__dict__ 属性中。也就是说,您可以做一些与您所拥有的类似的事情,但通过基类递归并打印出每个基类字典中的条目。

      另一种方法是使用dir(),它应该大致返回一个类所有属性的列表。我说大致是因为一个类可以实现__getattr____getattribute__ 以“即时”返回属性,这意味着该类可能没有为dir() 定义明确的属性集返回 - 请参阅完整的免责声明 here。但在许多常见情况下,类似以下的方法会起作用:

      class Meta(type):
          def __init__(cls, name, bases, attrs):
              print "bases = {}".format(bases)
              for attr in dir(cls):
                  if not attr.startswith('_'):
                      print attr, getattr(cls, attr)
      
      class Foo(object):
          __metaclass__ = Meta
          hi = 1
      
      class Bar(Foo):
          pass
      

      哪些打印:

      bases = (<type 'object'>,)
      hi 1
      bases = (<class '__main__.Foo'>,)
      hi 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-21
        • 1970-01-01
        • 1970-01-01
        • 2015-06-20
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 2020-11-24
        相关资源
        最近更新 更多