Как неоднократно отмечалось, использование имени функции — это динамический поиск в каталоге globals(). Работает только в модуле определения и только для глобальной функции. Если вы хотите узнать строку документа функции-члена, вам также нужно будет найти путь по имени класса, что довольно громоздко, поскольку эти имена могут быть довольно длинными:
def foo():
""" this is foo """
doc = foo.__doc__
class Foo:
def bar(self):
""" this is bar """
doc = Foo.bar.__doc__
эквивалентно
def foo():
""" this is foo """
doc = globals()["foo"].__doc__
class Foo:
def bar(self):
""" this is bar """
doc = globals()["Foo"].bar.__doc__
Если вы хотите найти строку документа вызывающего объекта, это в любом случае не сработает, поскольку ваш вспомогательный модуль печати может находиться в совершенно другом модуле с совершенно другим словарем globals(). Единственный правильный выбор - заглянуть во фрейм стека, но Python не дает вам исполняемый объект функции, он имеет только ссылку на объект кода "f_code". Но продолжайте, так как есть еще ссылка на "f_globals" этой функции. Таким образом, вы можете написать функцию для получения документа вызывающего абонента, подобного этому, и в качестве варианта вы получите свою собственную строку документа.
import inspect
def get_caller_doc():
frame = inspect.currentframe().f_back.f_back
for objref in frame.f_globals.values():
if inspect.isfunction(objref):
if objref.func_code == frame.f_code:
return objref.__doc__
elif inspect.isclass(objref):
for name, member in inspect.getmembers(objref):
if inspect.ismethod(member):
if member.im_func.func_code == frame.f_code:
return member.__doc__
и пошли тестить:
def print_doc():
print get_caller_doc()
def foo():
""" this is foo """
print_doc()
class Foo:
def bar(self):
""" this is bar """
print_doc()
def nothing():
print_doc()
class Nothing:
def nothing(self):
print_doc()
foo()
Foo().bar()
nothing()
Nothing().nothing()
# and my doc
def get_my_doc():
return get_caller_doc()
def print_my_doc():
""" showing my doc """
print get_my_doc()
print_my_doc()
результаты в этом выводе
this is foo
this is bar
None
None
showing my doc
На самом деле, большинству людей нужна их собственная строка документа только для того, чтобы передавать ее в качестве аргумента, но вызываемая вспомогательная функция может искать ее самостоятельно. Я использую это в своем коде unittest, где это иногда удобно для заполнения некоторых журналов или для использования строки документа в качестве тестовых данных. Вот почему представленный get_caller_doc() ищет только глобальные тестовые функции и функции-члены тестового класса, но я думаю, что этого достаточно для большинства людей, которые хотят узнать о строке документа.
class FooTest(TestCase):
def get_caller_doc(self):
# as seen above
def test_extra_stuff(self):
""" testing extra stuff """
self.createProject("A")
def createProject(self, name):
description = self.get_caller_doc()
self.server.createProject(name, description)
Определение правильного get_frame_doc(frame) с помощью sys._getframe(1) остается за читателем().
person
Guido U. Draheim
schedule
28.08.2014