您将如何确定Python类的每个属性和方法的定义位置?


问题内容

给定Python中某个类的实例,能够确定源代码的哪一行 定义了
每个方法和属性(例如,实现1)将很有用。例如,给定一个模块ab.py

class A(object):
    z = 1
    q = 2
    def y(self): pass
    def x(self): pass

class B(A):
    q = 4
    def x(self): pass
    def w(self): pass

定义一个函数whither(class_,attribute),该函数返回一个元组,该元组包含源代码中定义或子类化的文件名,类和行attribute。这意味着在班级主体中进行定义,而不是由于过度的动态性而导致的最新任务。如果它为某些属性返回“未知”,那就很好。

>>> a = A()
>>> b = B()
>>> b.spigot = 'brass'
>>> whither(a, 'z')
("ab.py", <class 'a.A'>, [line] 2)
>>> whither(b,  'q')
("ab.py", <class 'a.B'>, 8)
>>> whither(b, 'x')
("ab.py", <class 'a.B'>, 9)
>>> whither(b, 'spigot')
("Attribute 'spigot' is a data attribute")

我想在对Plone进行内省时使用它,其中每个对象都有数百种方法,对按类而不是按字母顺序组织的方法进行排序将非常有用。

当然,在Python中您可能永远无法合理地知道,但是在大多数为静态代码的常见情况下,获得良好答案将是很好的。


问题答案:

您正在寻找未记录的功能inspect.classify_class_attrs(cls)。将它传递给一个类,它将返回一个元组列表('name', 'kind' e.g. 'method' or 'data', defining class, property)。如果您需要有关特定实例中绝对所有内容的信息,则必须进行其他工作。

例:

>>> import inspect
>>> import pprint
>>> import calendar
>>> 
>>> hc = calendar.HTMLCalendar()
>>> hc.__class__.pathos = None
>>> calendar.Calendar.phobos = None
>>> pprint.pprint(inspect.classify_class_attrs(hc.__class__))
[...
 ('__doc__',
  'data',
  <class 'calendar.HTMLCalendar'>,
  '\n    This calendar returns complete HTML pages.\n    '),
 ...
 ('__new__',
  'data',
  <type 'object'>,
  <built-in method __new__ of type object at 0x814fac0>),
 ...
 ('cssclasses',
  'data',
  <class 'calendar.HTMLCalendar'>,
  ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']),
 ('firstweekday',
  'property',
  <class 'calendar.Calendar'>,
  <property object at 0x98b8c34>),
 ('formatday',
  'method',
  <class 'calendar.HTMLCalendar'>,
  <function formatday at 0x98b7bc4>),
 ...
 ('pathos', 'data', <class 'calendar.HTMLCalendar'>, None),
 ('phobos', 'data', <class 'calendar.Calendar'>, None),
 ...
 ]