How to print Docstring of python function from inside the function itself?
我想从函数本身内部打印python函数的docstring。例如
1 2 3 | def my_function(self): """Doc string for my function.""" # print the Docstring here. |
目前,我是在定义了
1 | print my_function.__doc__ |
但更愿意让函数自己来做。
我试过在我的函数内调用
1 2 3 | def my_func(): """Docstring goes here.""" print my_func.__doc__ |
只要您不将绑定到名称
1 2 3 4 5 | 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 |
你这样做的情况是相当罕见的,但它们确实发生了。
但是,如果您编写这样的装饰器:
1 2 3 4 | def passmein(func): def wrapper(*args, **kwargs): return func(func, *args, **kwargs) return wrapper |
现在您可以这样做:
1 2 3 | @passmein def my_func(me): print me.__doc__ |
这将确保您的函数得到对自身的引用(类似于
这应该有效(在我的测试中,它确实有效,还包括输出)。你可以用
类、方法和函数的示例。如果不是你要找的,告诉我:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 |
这工作:
1 2 3 4 5 6 | def my_function(): """Docstring for my function""" #print the Docstring here. print my_function.__doc__ my_function() |
在Python 2.7.1中
这也适用于:
1 2 3 4 5 6 7 8 9 10 11 | 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() |
然而,这不会单独起作用:
1 2 3 4 5 6 7 8 9 10 | class MyClass(object): def my_function(self): """Docstring for my function""" #print the Docstring here. print my_function.__doc__ foo = MyClass() foo.my_function() |
名称错误:未定义全局名称"我的函数"
有一个非常简单的方法可以做到这一点,但还没有人提到:
1 2 3 4 5 | import inspect def func(): """Doc string""" print inspect.getdoc(func) |
这就是你想要的。
这里没有什么好奇心。所发生的一切是,通过在函数中执行
我将它与docopt一起用于控制台脚本入口点。
你提出的问题就像是一个类方法而不是一个函数。命名空间在这里很重要。对于一个函数,
对于一个类方法,那么
如果您不想指定方法的名称,而是传递一个变量给它,您可以使用内置函数hasattr(object,attribute)和getattr(obj,attr),正如它们所说的那样,允许您通过字符串作为方法名传递变量。例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 ) |
如前所述,使用函数名是globals()目录中的动态查找。它只在定义的模块中工作,并且只适用于全局函数。如果要查找成员函数的Doc字符串,还需要从类名中查找路径-这很麻烦,因为这些名称可能会变长:
1 2 3 4 5 6 7 | def foo(): """ this is foo""" doc = foo.__doc__ class Foo: def bar(self): """ this is bar""" doc = Foo.bar.__doc__ |
相当于
1 2 3 4 5 6 7 | def foo(): """ this is foo""" doc = globals()["foo"].__doc__ class Foo: def bar(self): """ this is bar""" doc = globals()["Foo"].bar.__doc__ |
如果您想查找调用方的DOC字符串,那么这将不起作用,因为您的打印助手可能与完全不同的全局()字典位于完全不同的模块中。唯一正确的选择是查看堆栈帧——但是Python没有给您执行正在执行的函数对象,它只引用了一个"fxCal码"代码对象。但是继续前进,因为还有一个函数的"fGULL"的引用。因此,您可以编写一个函数来获取调用方的doc,并且作为变量,您可以得到自己的DOC字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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__ |
让我们来测试一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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() |
在这个输出中的结果
1 2 3 4 5 | this is foo this is bar None None showing my doc |
实际上,大多数人只希望自己的文档字符串作为一个参数传递下去,但是被调用的helper函数可以自己查找所有这些字符串。我在我的UnitTest代码中使用它,在这里有时填充一些日志或使用文档字符串作为测试数据很方便。这就是为什么所呈现的get_caller_doc()只查找测试类的全局测试函数和成员函数的原因,但我想这对于大多数想了解文档字符串的人来说已经足够了。
1 2 3 4 5 6 7 8 9 | 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(frame)with sys._getframe(1)留给reader()。
尝试:
1 2 3 4 5 6 | class MyClass(): # ... def my_function(self): """Docstring for my function""" print MyClass.my_function.__doc__ # ... |
(*)
插入