Как печатать Docstring функции Python изнутри самой функции?
Вопрос
Я хочу распечатать Docstring функции Python изнутри самой функции. Например.
def my_function(self):
"""Doc string for my function."""
# print the Docstring here.
На данный момент я делаю это сразу после my_function
был определен.
print my_function.__doc__
Но предпочел бы позволить функции сделать это сам.
Я пытался позвонить print self.__doc__
print self.my_function.__doc__
а также print this.__doc__
Внутри my_function, но это не сработало.
Решение
def my_func():
"""Docstring goes here."""
print my_func.__doc__
Это будет работать до тех пор, пока вы не измените объект, связанный с именем my_func
.
new_func_name = my_func
my_func = None
new_func_name()
# doesn't print anything because my_func is None and None has no docstring
Ситуации, в которых вы это делаете, довольно редки, но они случаются.
Однако, если вы напишете декоратор, как это:
def passmein(func):
def wrapper(*args, **kwargs):
return func(func, *args, **kwargs)
return wrapper
Теперь вы можете сделать это:
@passmein
def my_func(me):
print me.__doc__
И это гарантирует, что ваша функция получит ссылку на себя (аналогично self
) в качестве первого аргумента, так что он всегда может получить док -строение правильной функции. Если используется на методе, обычный self
становится вторым аргументом.
Другие советы
Это должно работать (в моих тестах, это также включает в себя вывод). Вы могли бы использовать __doc__
Вместо getdoc, но мне это нравится, так что это то, что я использовал. Кроме того, это не требует, чтобы вы узнали имена класса/метода/функции.
Примеры как для класса, метода и функции. Скажи мне, не то, что ты искал :)
from inspect import *
class MySelfExplaningClass:
"""This is my class document string"""
def __init__(self):
print getdoc(self)
def my_selfexplaining_method(self):
"""This is my method document string"""
print getdoc(getattr(self, getframeinfo(currentframe()).function))
explain = MySelfExplaningClass()
# Output: This is my class document string
explain.my_selfexplaining_method()
# Output: This is my method document string
def my_selfexplaining_function():
"""This is my function document string"""
print getdoc(globals()[getframeinfo(currentframe()).function])
my_selfexplaining_function()
# Output: This is my function document string
Это работает:
def my_function():
"""Docstring for my function"""
#print the Docstring here.
print my_function.__doc__
my_function()
в Python 2.7.1
Это также работает:
class MyClass(object):
def my_function(self):
"""Docstring for my function"""
#print the Docstring here, either way works.
print MyClass.my_function.__doc__
print self.my_function.__doc__
foo = MyClass()
foo.my_function()
Это, однако, не будет работать самостоятельно:
class MyClass(object):
def my_function(self):
"""Docstring for my function"""
#print the Docstring here.
print my_function.__doc__
foo = MyClass()
foo.my_function()
Nameerror: глобальное имя 'my_function' не определено
Вы задали свой вопрос как метод класса, а не функцию. Пространства имен важны здесь. Для функции, print my_function.__doc__
это нормально, так как my_function находится в глобальном пространстве имен.
Для метода класса, тогда print self.my_method.__doc__
будет путь.
Если вы не хотите указывать имя метода, а скорее передавать его переменной, вы можете использовать встроенные функции hasattr (объект, атрибут) и getattr (obj, attr), которые делают, как говорят, позволяя вам передать переменные с струнами, являющимися названием метода. например
class MyClass:
def fn(self):
"""A docstring"""
print self.fn.__doc__
def print_docstrings(object):
for method in dir( object ):
if method[:2] == '__': # A protected function
continue
meth = getattr( object, method )
if hasattr( meth , '__doc__' ):
print getattr( meth , '__doc__' )
x = MyClass()
print_docstrings( x )
Есть довольно простой метод для этого, о котором никто еще не упомянул:
import inspect
def func():
"""Doc string"""
print inspect.getdoc(func)
И это делает то, что вы хотите.
Здесь нет ничего особенного. Все, что происходит, это то, что делая func.__doc__
в функции Defers Attribute разрешение атрибутов достаточно долго, чтобы найти вверх __doc__
На этом работа, как и следовало ожидать.
Я использую это с docopt для точек входа сценария консоли.
Пытаться:
class MyClass():
# ...
def my_function(self):
"""Docstring for my function"""
print MyClass.my_function.__doc__
# ...
(*) Была толстая кишка (:
) отсутствует после my_function()
Как отмечалось много раз, использование имени функции является динамическим поиском в каталоге Global (). Он работает только в модуле определения и только для глобальной функции. Если вы хотите узнать строку DOC функции участника, вам нужно также искать путь от имени класса, что довольно громоздко, так как эти имена могут стать довольно длинными:
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__
Если вы хотите найти строку DOC Aller, это все равно не сработает, так как ваш печатный шлюз может жить в совершенно другом модуле с совершенно другим словарным (). Единственный правильный выбор - заглянуть в кадр стека - но Python не дает вам выполняемого объекта функции, он имеет только ссылку на объект кода «F_CODE». Но продолжайте, так как есть также ссылка на «f_globals» этой функции. Таким образом, вы можете написать функцию, чтобы получить так, как это так, и в качестве вариации, вы получаете свою собственную строку DOC.
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
На самом деле, большинство людей хотят, чтобы их собственная строка DOC только выпустила ее в качестве аргумента, но вызываемая вспомогательная функция может найти все это самостоятельно. Я использую это в своем коде Unittest, где это иногда удобно заполнить некоторые журналы или использовать строку DOC в качестве тестовых данных. Вот почему представленная get_caller_doc () ищет только глобальные функции тестирования и функции членов тестового класса, но я думаю, этого достаточно для большинства людей, которые хотят узнать о строке 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 (кадр) с помощью sys._getframe (1) остается для reader ().
вставкаprint __doc__
Сразу после объявления класса, до def __init__
, будет печатать строку DOC в консоли каждый раз, когда вы инициируете объект с классом