如何访问 Python 超类的属性,例如通过 __class__.__dict__?

Posted

技术标签:

【中文标题】如何访问 Python 超类的属性,例如通过 __class__.__dict__?【英文标题】:How to access properties of Python super classes e.g. via __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,因为我只需要属性。 重复***.com/questions/8529192/… 【参考方案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)
>>> 

【讨论】:

以上是关于如何访问 Python 超类的属性,例如通过 __class__.__dict__?的主要内容,如果未能解决你的问题,请参考以下文章

Python - 访问类的受保护成员_

python 基础语法 _的识别方法

说说 Python 的继承

python 创建和类属性同名的实例属性,通过实例访问就是实例属性,通过类访问的属性就是类的属性

面向对象之继承——python篇

super() 和直接调用超类的区别