Как бы вы определили, где определено каждое свойство и метод класса Python?

StackOverflow https://stackoverflow.com/questions/484890

Вопрос

Учитывая экземпляр некоторого класса в 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

определите функцию, которая (class_, атрибут) возвращает кортеж, содержащий имя файла, класс и строку в исходном коде, который определил или подклассировал attribute.Это означает определение в теле класса, а не последнее присвоение из-за чрезмерной динамичности.Это нормально, если он возвращает 'unknown' для некоторых атрибутов.

>>> 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 вы не всегда можете точно знать, но было бы неплохо получить хорошие ответы в обычном случае преимущественно статического кода.

Это было полезно?

Решение 2

Вы ищете недокументированную функцию 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),
 ...
 ]

Другие советы

Это более или менее невозможно без статического анализа, и даже тогда это не всегда будет работать.Вы можете получить строку, где была определена функция и в каком файле, изучив ее объект code, но помимо этого вы мало что можете сделать.В inspect модуль может помочь в этом.Итак:

import ab
a = ab.A()
meth = a.x
# So, now we have the method.
func = meth.im_func
# And the function from the method.
code = func.func_code
# And the code from the function!
print code.co_firstlineno, code.co_filename

# Or:
import inspect
print inspect.getsource(meth), inspect.getfile(meth)

Но подумайте:

def some_method(self):
    pass
ab.A.some_method = some_method
ab.A.some_class_attribute = None

Или еще хуже:

some_cls = ab.A
some_string_var = 'another_instance_attribute'
setattr(some_cls, some_string_var, None)

Особенно в последнем случае, чего вы хотите или ожидаете получить?

Вы ищете Осмотр модуль, в частности inspect.getsourcefile() и inspect.getsourcelines().Например

a.py:

class Hello(object):
    def say(self):
       print 1

>>> from a import Hello
>>> hi = Hello()
>>> inspect.getsourcefile(hi.say)
a.py
>>> inspect.getsourcelines(A, foo)
(['   def say(self):\n        print 1\n'], 2)

Учитывая динамическую природу Python, сделать это для более сложных ситуаций может быть просто невозможно...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top