propias - ¿Cómo imprimir Docstring de la función python desde el interior de la función?
lista de funciones de python (8)
Como se señaló muchas veces, usar el nombre de la función es una búsqueda dinámica en el directorio de globals (). Solo funciona en el módulo de la definición y solo para una función global. Si desea averiguar la secuencia de documentación de una función miembro, también deberá buscar la ruta desde el nombre de la clase, lo cual es bastante engorroso, ya que estos nombres pueden ser bastante largos:
def foo():
""" this is foo """
doc = foo.__doc__
class Foo:
def bar(self):
""" this is bar """
doc = Foo.bar.__doc__
es equivalente a
def foo():
""" this is foo """
doc = globals()["foo"].__doc__
class Foo:
def bar(self):
""" this is bar """
doc = globals()["Foo"].bar.__doc__
Si desea buscar la cadena de texto de la persona que llama, eso no funcionará de todos modos, ya que su asistente de impresión podría vivir en un módulo completamente diferente con un diccionario de globals () completamente diferente. La única opción correcta es mirar dentro del marco de pila, pero Python no le da el objeto de función que se está ejecutando, solo tiene una referencia al objeto de código "f_code". Pero sigue, ya que también hay una referencia a los "f_globals" de esa función. Por lo tanto, puede escribir una función para obtener el documento de la persona que llama así, y como una variación de él, obtiene su propia cadena de documentación.
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__
y vamos a probarlo:
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()
resultados en esta salida
this is foo
this is bar
None
None
showing my doc
En realidad, la mayoría de la gente quiere su propia cadena de documentación para presentarla como argumento, pero la función de ayuda llamada puede buscarla por sí misma. Estoy usando esto en mi código unittest, donde a veces es útil llenar algunos registros o usar la cadena de documentos como datos de prueba. Esa es la razón por la cual get_caller_doc () presentado solo busca las funciones de prueba globales y las funciones de miembro de una clase de prueba, pero supongo que eso es suficiente para la mayoría de las personas que desean averiguar acerca de la cadena de documentación.
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)
Para definir un get_frame_doc (frame) apropiado con sys._getframe (1) se deja al lector ().
Quiero imprimir el docstring de una función de python desde el interior de la función. por ej.
def my_function(self):
"""Doc string for my function."""
# print the Docstring here.
Por el momento, estoy haciendo esto directamente después de que se haya definido mi función.
print my_function.__doc__
Pero preferiría que la función lo hiciera por sí misma.
Intenté llamar al print self.__doc__
print self.my_function.__doc__
e print this.__doc__
dentro de mi_función pero esto no funcionó.
Esto debería funcionar (en mis pruebas lo hace, también incluye salida). Probablemente __doc__
usar __doc__
lugar de getdoc, pero me gusta, así que es exactamente lo que usé. Además, esto no requiere que sepas los nombres de la clase / método / función.
Ejemplos tanto para una clase, un método y una función. Dime si no es lo que estabas buscando :)
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
Esto funciona:
def my_function():
"""Docstring for my function"""
#print the Docstring here.
print my_function.__doc__
my_function()
en Python 2.7.1
Esto también funciona:
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()
Sin embargo, esto no funcionará solo:
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: el nombre global ''my_function'' no está definido
Ha planteado su pregunta como un método de clase en lugar de una función. Los espacios de nombre son importantes aquí. Para una función, print my_function.__doc__
está bien, ya que my_function está en el espacio de nombres global.
Para un método de clase, print self.my_method.__doc__
sería el camino a seguir.
Si no desea especificar el nombre del método, sino pasarle una variable, puede usar las funciones incorporadas hasattr (objeto, atributo) y getattr (obj, attr), que hacen lo que dicen, permitiéndole pasar variables con cadenas como el nombre de un método. p.ej
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 )
Hay un método bastante simple para hacer esto que nadie ha mencionado aún:
import inspect
def func():
"""Doc string"""
print inspect.getdoc(func)
Y esto hace lo que quieres.
No hay nada elegante pasando aquí. Todo lo que sucede es que al hacer func.__doc__
en una función se difiere la resolución de los atributos el tiempo suficiente para buscar __doc__
en el trabajo como se espera.
Lo uso con docopt para los puntos de entrada del script de consola.
Tratar:
class MyClass():
# ...
def my_function(self):
"""Docstring for my function"""
print MyClass.my_function.__doc__
# ...
(*) my_function()
dos my_function()
después de my_function()
insertando print __doc__
justo después de la declaración de clase, antes de la def __init__
, imprimirá la cadena de documentación en la consola cada vez que inicie un objeto con la clase
def my_func():
"""Docstring goes here."""
print my_func.__doc__
Esto funcionará siempre que no cambie el objeto vinculado al nombre 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
Las situaciones en las que harías esto son bastante raras, pero suceden.
Sin embargo, si escribes un decorador como este:
def passmein(func):
def wrapper(*args, **kwargs):
return func(func, *args, **kwargs)
return wrapper
Ahora puedes hacer esto:
@passmein
def my_func(me):
print me.__doc__
Y esto asegurará que su función se haga una referencia a sí misma (similar a self
) como su primer argumento, por lo que siempre puede obtener el docstring de la función correcta. Si se utiliza en un método, el self
habitual self
convierte en el segundo argumento.