想象一下一个类的实例有一个属性attr。我想知道它是从哪里获得的。
让我们考虑一下Python中的这两种情况:
class vehicle():
speed = 5
class flying_machine(vehicle):
density = 1
还有
class vehicle():
def __init__(self):
self.speed = 5
class flying_machine(vehicle):
def __init__(self):
super().__init__()
self.density = 1
如果执行以下代码行:
b = flying_machine()
s = b.speed
s的值为5。这两种情况都不同,在第一种情况下,速度是“车辆”类的属性,在另一种情况下,速度是在“车辆”类的实例的属性。
我的问题在两种情况下都是相同的,我想知道b从哪里获得了他的属性“ speed”,我想拥有一个可以调用b和“ speed”的函数,并将我指向该地点定义了b.speed的位置。
在我的示例中,很容易看到b从何处获得其属性,但是您可以想象在多个文档中定义了类和子类,并且它们具有长的继承链。例如:
# doc1.py
class vehicle():
speed = 5
# doc2.py
from doc1.py import *
class flying_machine(vehicle):
density = 1
# doc3.py
from doc2.py import *
class space_machine(flying_machine):
light_speed = 0.5
# main.py
from doc3.py import *
c = space_machine()
在最后一种情况下,我的c具有一个属性速度,如果我想查看它的来源,我必须经历所有先前的导入,在那儿有一个函数可以告诉我, c.speed来自doc1.py。
答案 0 :(得分:2)
通常,我建议您使用PyCharm之类的适当IDE,该IDE允许您 Ctrl +单击任何属性,然后将您导航到该属性的分配位置。 / p>
话虽如此,您可以使用类的mro通过检查实例及其类的__dict__
和{{ 3}}:
def lookup(obj, attr):
if attr in obj.__dict__ or attr in obj.__slots__:
print('{}: instance attribute'.format(attr))
klass = next((k for k in obj.__class__.mro()
if '__slots__' in k.__dict__ and attr in k.__slots__),
None)
if klass:
print('but expected for class {}'.format(klass))
else:
for klass in obj.__class__.mro():
if attr in klass.__dict__:
print('{}: class attribute of {}'.format(attr, klass))
您可以将此函数用于任意对象和属性:
class Vehicle:
speed = 5
class Ugly:
__slots__ = ('look',)
def __init__(self):
self.look = 'terrible'
class Car(Ugly, Vehicle):
def __init__(self):
super().__init__()
self.num_wheels = 4
>>> c = Car()
>>> lookup(c, 'speed')
speed: class attribute of <class '__main__.Vehicle'>
>>> lookup(c, 'num_wheels')
num_wheels: instance attribute
>>> lookup(c, 'look')
look: instance attribute
but expected for class <class '__main__.Ugly'>