Как печатать 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, но это не сработало.

Ответ 1

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) в качестве своего первого аргумента, поэтому она всегда может получить docstring правильной функции. Если используется метод, обычный self становится вторым аргументом.

Ответ 2

Это должно работать (в моих тестах оно также включает вывод). Вероятно, вы можете использовать __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

Ответ 3

Это работает:

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' не определено

Ответ 4

Вы задали свой вопрос как метод класса, а не функцию. Пространства имен важны здесь. Для функции 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 )

Ответ 5

Попробуйте:

class MyClass():
    # ...
    def my_function(self):
        """Docstring for my function"""
        print MyClass.my_function.__doc__
        # ...

(*) Произошла двоеточие (:) после my_function()

Ответ 6

Существует довольно простой способ сделать это, о котором никто еще не упомянул:

import inspect

def func():
    """Doc string"""
    print inspect.getdoc(func)

И это делает то, что вы хотите.

Здесь нет ничего интересного. Все, что происходит, заключается в том, что, выполняя func.__doc__ в функции, исправляет разрешение атрибута достаточно долго, чтобы смотреть вверх __doc__ на нем работает так, как вы ожидали.

Я использую это с docopt для консольных точек доступа script.

Ответ 7

Как отмечалось много раз, использование имени функции - это динамический поиск в каталоге globals(). Он работает только в модуле определения и только для глобальной функции. Если вы хотите узнать строку 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__

Если вы хотите посмотреть строку документа вызывающего, это не будет работать, так как ваш помощник по печати может жить в совершенно другом модуле с совершенно другим словарем 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-коде, где это иногда удобно заполнять некоторые журналы или использовать строку doc в качестве тестовых данных. Причина, по которой представленный 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 (фрейма) с sys._getframe (1) остается читатель().

Ответ 8

вставка print __doc__ сразу после объявления класса перед def __init__ будет печатать строку doc на консоли каждый раз, когда вы инициируете объект с классом