Jak wydrukować Docstring funkcji Pythona z wnętrza samej funkcji?

Chcę wydrukować docstring funkcji Pythona z wnętrza samej funkcji. dla np.

def my_function(self):
  """Doc string for my function."""
  # print the Docstring here.

W tej chwili robię to bezpośrednio po zdefiniowaniu my_function.

print my_function.__doc__

Ale wolałby, aby funkcja sama to zrobiła.

Próbowałem się dodzwonić print self.__doc__ print self.my_function.__doc__ i print this.__doc__ wewnątrz my_function, ale to nie zadziałało.

Author: he1ix, 2012-01-11

8 answers

def my_func():
    """Docstring goes here."""
    print my_func.__doc__

Będzie to działać tak długo, jak długo nie zmienisz obiektu związanego z nazwą 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
Sytuacje, w których można to zrobić, są raczej rzadkie, ale zdarzają się.

Jeśli jednak napiszesz taki dekorator:

def passmein(func):
    def wrapper(*args, **kwargs):
        return func(func, *args, **kwargs)
    return wrapper

Teraz możesz to zrobić:

@passmein
def my_func(me):
    print me.__doc__

I to zapewni, że twoja funkcja otrzyma odniesienie do siebie (podobne do self) jako pierwszy argument, więc zawsze może uzyskać docstring właściwej funkcji. W przypadku zastosowania metody, Zwykle self staje się drugim argumentem.

 78
Author: kindall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-07 12:26:30

To powinno zadziałać(w moich testach tak jest, także wyjście). Prawdopodobnie mógłbyś użyć __doc__ zamiast getdoc, ale podoba mi się, więc właśnie tego użyłem. Nie wymaga to również znajomości nazw klasy / metody / funkcji.

Przykłady zarówno dla klasy, metody i funkcji. Powiedz mi, czy to nie to, czego szukałeś:)

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
 10
Author: Tehnix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-12 01:12:52

To działa:

def my_function():
  """Docstring for my function"""
  #print the Docstring here.
  print my_function.__doc__

my_function()

W Pythonie 2.7.1

To również działa:

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()

To jednak nie zadziała samo:

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: globalna nazwa 'my_function' nie jest zdefiniowana

 6
Author: jgritty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-12 00:24:34

Jest na to dość prosta metoda, o której nikt jeszcze nie wspomniał:

import inspect

def func():
    """Doc string"""
    print inspect.getdoc(func)
A to robi, co chcesz. Nie ma tu nic wymyślnego. Wszystko, co się dzieje, to to, że wykonywanie func.__doc__ w funkcji opóźnia rozdzielczość atrybutów na tyle długo, aby patrząc w górę __doc__ działało tak, jak można się spodziewać.

Używam tego z docopt dla punktów wprowadzania skryptów konsoli.

 4
Author: Keith Gaughan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-11 13:27:55

Postawiłeś swoje pytanie jak metodę klasową, a nie jak funkcję. Przestrzenie nazw są tutaj ważne. Dla funkcji print my_function.__doc__ jest w porządku, ponieważ my_function znajduje się w globalnej przestrzeni nazw.

Dla metody klasowej, wtedy print self.my_method.__doc__ byłoby to droga do zrobienia.

Jeśli nie chcesz podawać nazwy metody, ale raczej przekazać do niej zmienną, możesz użyć wbudowanych funkcji hasattr (object,attribute) i getattr (obj, attr), które robią to, co mówią, umożliwiając przekazywanie zmiennych za pomocą ciągi będące nazwą metody. np.

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 )
 2
Author: Alex Leach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-11 17:24:25

Jak zauważono wiele razy, użycie nazwy funkcji jest dynamicznym wyszukiwaniem w katalogu globals (). Działa tylko w module definicji i tylko dla funkcji globalnej. Jeśli chcesz dowiedzieć się o łańcuchu doc funkcji członka, musisz również wyszukać ścieżkę z nazwy klasy - co jest dość kłopotliwe, ponieważ nazwy te mogą być dość długie:

def foo():
    """ this is foo """
    doc = foo.__doc__
class Foo:
    def bar(self):
       """ this is bar """
       doc = Foo.bar.__doc__

Jest równoważne

def foo():
    """ this is foo """
    doc = globals()["foo"].__doc__
class Foo:
    def bar(self):
       """ this is bar """
       doc = globals()["Foo"].bar.__doc__

Jeśli chcesz sprawdzić ciąg doc rozmówcy, to i tak nie będzie działać jako twój Print-helper może żyć w zupełnie innym module z zupełnie innym słownikiem globals (). Jedynym prawidłowym wyborem jest zajrzenie do ramki stosu - ale Python nie podaje wykonywanego obiektu funkcji, ma tylko odniesienie do obiektu kodu "f_code". Ale kontynuuj, ponieważ jest również odniesienie do "f_globals" tej funkcji. Więc możesz napisać funkcję, aby uzyskać Doc rozmówcy w ten sposób, a jako wariację od niego, masz swój własny doc sznurek.

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__

I chodźmy to przetestować:

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()

Wyniki w tym wyjściu

 this is foo 
 this is bar 
None
None
 showing my doc 

Właściwie, większość ludzi chce mieć własny ciąg doc tylko po to, aby przekazać go jako argument, ale wywołana funkcja helpera może sam go wyszukać. Używam tego w moim kodzie unittest, gdzie jest to czasami przydatne do wypełnienia niektórych dzienników lub do użycia ciągu doc jako danych testowych. To jest powód, dla którego przedstawiona get_caller_doc () szuka tylko globalnych funkcji testowych i funkcji Członkowskich Klasa testowa, ale to chyba wystarczy dla większości osób, które chcą się dowiedzieć o Doc string.

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)

Aby zdefiniować właściwy get_frame_doc (ramka) z sys._getframe (1) jest pozostawione do reader().

 2
Author: Guido U. Draheim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-28 13:10:19

Try:

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

(*) brakowało dwukropka (:) po my_function()

 1
Author: juliomalegria,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-11 16:22:51

Wstawianie print __doc__ tuż po deklaracji klasy, przed def __init__, wyświetli ciąg doc do konsoli za każdym razem, gdy zainicjujesz obiekt z klasą

 0
Author: emorphus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-08 18:06:06