Jak mogę wyprowadzić Docstring funkcji Pythona z samej funkcji?


Chcę wydrukować wiersz dokumentu funkcji Pythona z samej funkcji.
na przykład.
def my_function(self):
"""Doc string for my function."""
# print the Docstring here.

W tej chwili robię to zaraz po definicji
my_function
.
print my_function.__doc__

Ale lepiej pozwolić funkcji zrobić to sama.
Próbowałem zadzwonić do
print self .__ doc__
print self.my_function .__ doc__
i
print this .__ doc__
inside my_function, ale tak się nie stało praca.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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

To zadziała, o ile nie zmienisz obiektu przypisanego do nazwy
my_func
.
new_func_name = my_func
my_func = Nonenew_func_name()
# doesn't print anything because my_func is None and None has no docstring

Sytuacje, w których byś to zrobił, są dość rzadkie, ale zdarzają się.
Jeśli jednak napiszesz dekoratora w ten sposób:
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__

A to gwarantuje, że twoja funkcja otrzyma odwołanie do samej siebie (podobnie do
self
) jako pierwszy argument, dzięki czemu zawsze może uzyskać ciąg dokumentów do właściwej funkcji. W przypadku użycia w metodzie zwykłe
self
staje się drugim argumentem.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

To powinno zadziałać (w moich testach tak jest, dane wyjściowe są również uwzględnione). Prawdopodobnie mógłbyś użyć
__doc__
zamiast getdoc, ale podoba mi się to, więc właśnie tego użyłem. Nie wymaga również znajomości nazw klas/metod/funkcji.
Przykłady dla klasy, metody i funkcji. Powiedz mi, czy tego nie 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 stringexplain.my_selfexplaining_method()# Output: This is my method document stringdef 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
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ta praca:
def my_function():
"""Docstring for my function"""
#print the Docstring here.
print my_function.__doc__my_function()

w Pythonie 2.7.1
To też 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()

Jednak to nie zadziała samodzielnie:
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: nazwa globalna „moja_funkcja” jest niezdefiniowana
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jest na to dość prosty sposób, o którym nikt jeszcze nie wspomniał:
import inspectdef func():
"""Doc string"""
print inspect.getdoc(func)

I robi to, co chcesz.
Nie dzieje się tu nic specjalnego. Wszystko, co się dzieje, polega na tym, że wykonując
func .__ doc__
w funkcji, opóźnia ona rozdzielczość atrybutu wystarczająco długo, aby wyszukać na nim
__doc__
, aby działał zgodnie z oczekiwaniami.
Używam tego z docopt do punktów wejścia skryptów konsoli.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Zadałeś swoje pytanie jako metodę klasową, a nie funkcję. Przestrzenie nazw są tutaj ważne. W przypadku funkcji
print my_function .__ doc__
jest w porządku, ponieważ my_function znajduje się w globalnej przestrzeni nazw.
W przypadku metody klasowej najlepszym rozwiązaniem byłoby
print self.my_method .__ doc__
.
Jeśli nie chcesz podawać nazwy metody, ale zamiast tego przekazać do niej zmienną, możesz użyć wbudowanych funkcji hasattr (obiekt, atrybut) i getattr (obj, attr), które robią to, co mówią, pozwalając ci przekazywać zmienne, których nazwa metody jest napisem. dawny.
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 )
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jak wielokrotnie zauważano, użycie nazwy funkcji jest dynamicznym wyszukiwaniem w katalogu globals (). Działa tylko w module definicji i tylko dla funkcji globalnej. Jeśli chcesz poznać ciąg dokumentacyjny funkcji składowej, będziesz musiał również znaleźć ścieżkę z nazwy klasy - co jest dość uciążliwe, ponieważ te nazwy 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__

równoważny
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 spojrzeć na linię dokumentu wywołującego, to nadal nie będzie działać, ponieważ twój pomocnik drukowania może znajdować się w zupełnie innym module z zupełnie innym słownikiem globals (). Jedynym właściwym wyborem jest zajrzenie do ramki stosu, ale Python nie daje ci wykonywalnego obiektu funkcji, ma tylko odniesienie do obiektu kodu „f_code”. Ale kontynuuj, ponieważ istnieje również link do „f_globals” tej funkcji. Możesz więc napisać funkcję, która w ten sposób pobierze dokument wywołującego, a jako jej odmianę, otrzymasz swój własny opis.
import inspectdef 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 poszedłem to sprawdzić:
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 docdef get_my_doc():
return get_caller_doc()def print_my_doc():
""" showing my doc """
print get_my_doc()print_my_doc()

skutkuje tym wyjściem
this is foo 
this is bar
None
None
showing my doc

W rzeczywistości większość ludzi chce, aby ich własny ciąg dokumentacyjny był przekazywany tylko jako argument, ale wywołana funkcja pomocnicza może go samodzielnie szukać. Używam tego w moim Unittest Code, gdzie czasami przydatne jest wypełnienie niektórych dzienników lub użycie wiersza dokumentu jako danych testowych. To dlatego udostępniona funkcja get_caller_doc () szuka tylko globalnych funkcji testowych i funkcji składowych klasy testowej, ale myślę, że jest to wystarczające dla większości ludzi, którzy chcą wiedzieć o linii dokumentu.
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 określić poprawną get_frame_doc (ramkę) za pomocą sys._getframe (1), pozostaje reader ().
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

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

(*) Brak dwukropka po
my_function ()
(
:
)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

wstawienie
print __doc__
zaraz po deklaracji klasy, przed
def __init__
spowoduje wydrukowanie wiersza dokumentu na konsoli za każdym razem, gdy zainicjujesz obiekt z klasą

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się