【问题标题】:How to access properties of Python super classes e.g. via __class__.__dict__?如何访问 Python 超类的属性,例如通过 __class__.__dict__?
【发布时间】:2012-03-11 18:41:25
【问题描述】:

如何获取 python 类的所有属性名称包括从超类继承的那些属性

class A(object):
  def getX(self):
    return "X"
  x = property(getX)

a = A()
a.x
'X'

class B(A):
  y = 10

b = B()
b.x
'X'

a.__class__.__dict__.items()
[('__module__', '__main__'), ('getX', <function getX at 0xf05500>), ('__dict__', <attribute '__dict__' of 'A' objects>), ('x', <property object at 0x114bba8>), ('__weakref__', <attribute '__weakref__' of 'A' objects>), ('__doc__', None)]
b.__class__.__dict__.items()
[('y', 10), ('__module__', '__main__'), ('__doc__', None)]

如何通过 b 访问 a 的属性? 需要:“给我一份来自 b 的所有 属性 名称的列表,包括从 a 继承的那些!”

>>> [q for q in a.__class__.__dict__.items() if type(q[1]) == property]
[('x', <property object at 0x114bba8>)]
>>> [q for q in b.__class__.__dict__.items() if type(q[1]) == property]
[]

当使用第二个 (b) 时,我想从第一个 (a) 中获取结果,但当前只能得到一个空列表。这也应该适用于从 B 继承的另一个 C。

【问题讨论】:

  • 请注意,y 不是属性,它只是一个整数。你想要所有可能不是函数的类变量吗?
  • 如果你关心 Python 风格(PEP 8),或者如果你不需要能够做函数调用版本(你会如果你通过super()---super(...).x = 'Y'设置属性会失败),只需使用property作为装饰器,如@propertydef x(self): return 'X'
  • 感谢这些 cmets。我试图创建一个简单的示例而不是我的复杂代码,是的,因此我没有考虑 PEP8。我不关心y,因为我只需要属性。

标签: python reflection properties parent introspection


【解决方案1】:

你可以使用dir():

for attr_name in dir(B):
    attr = getattr(B, attr_name)
    if isinstance(attr, property):
        print attr

【讨论】:

  • 好的,我想这对我有用,最后是 print attr_name, attr.__get__(b)。谢谢。
  • 感谢#python.de@irc.freenode.net 上的帮助,提供导致替代答案的提示:for c in b.__class__.__mro__: if issubclass(c, A): for p in [q for q in c.__dict__.items() if type(q[1]) == property]: print p[0], '=', p[1].__get__(b)
  • @user1156548:我认为没有必要自己走 MRO。你当然可以,但为什么应该你呢?
  • 使用 mro 的工作方式与上述 dir() 解决方案类似。没有这两者它是行不通的,因为 class.__dict__ 不包含超类的属性。你有什么建议@sven-marnach
  • @user1156548:我建议使用dir(),因为它更容易并且不会显示已被子类覆盖的属性——我猜你不希望它们出现两次。跨度>
【解决方案2】:

您可以使用“dir”,也可以遵循“mro”返回的元组中包含的所有类(方法解析顺序,由类上的__mro__ 属性给出) - 后一种方法是发现后来被子类覆盖的属性的唯一方法:

>>> class A(object):
...    b = 0
... 
>>> class B(A):
...   b = 1
... 
>>> for cls in B.__mro__:
...     for item in cls.__dict__.items():
...         if item[0][:2] != "__":
...            print cls.__name__, item
... 
B ('b', 1)
A ('b', 0)
>>> 

【讨论】:

    猜你喜欢
    • 2010-09-30
    • 2018-01-01
    • 2011-06-20
    • 2020-04-18
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    相关资源
    最近更新 更多