Как уже много раз отмечалось, использование имени функции - это динамический поиск в каталоге globals ().Он работает только в модуле определения и только для глобальной функции.Если вы хотите узнать строку документа функции-члена, вам также необходимо найти путь к имени класса, что довольно громоздко, поскольку эти имена могут быть довольно длинными:
def foo():
""" this is foo """
doc = foo.__doc__
class Foo:
def bar(self):
""" this is bar """
doc = Foo.bar.__doc__
эквивалентноto
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__
, и давайте протестируем ее:
приводит к таким выводам
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), оставляем читателю ().