Как печатать Docstring функции Python изнутри самой функции?

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

Вопрос

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

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