如何从函数本身内部打印python函数的Docstring?

时间:2012-01-11 16:17:04

标签: python function printing docstring

我想从函数本身内部打印python函数的docstring。 例如。

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

目前我在定义my_function后直接这样做。

print my_function.__doc__

但宁愿让函数自己这样做。

我尝试在my_function中调用print self.__doc__ print self.my_function.__doc__print this.__doc__,但这不起作用。

8 个答案:

答案 0 :(得分:62)

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)作为其第一个参数,因此它始终可以获取正确函数的文档字符串。如果在方法上使用,通常self成为第二个参数。

答案 1 :(得分:8)

这应该有效(在我的测试中它也可以,也包括输出)。您可以使用__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

答案 2 :(得分:5)

这有效:

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'

答案 3 :(得分:2)

你提出的问题就像一个类方法而不是一个函数。命名空间在这里很重要。对于函数,print my_function.__doc__没问题,因为my_function在全局命名空间中。

对于一个类方法,然后print self.my_method.__doc__就可以了。

如果您不想指定方法的名称,而是将变量传递给它,则可以使用内置函数hasattr(object,attribute)和getattr(obj,attr),他们说,允许你传递变量,字符串是方法的名称。 e.g。

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 )

答案 4 :(得分:1)

尝试:

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

(*):

后有一个冒号(my_function())丢失

答案 5 :(得分:1)

如前所述,使用函数名称是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__

如果你想查找调用者的doc字符串,那么无论如何你都不会工作,因为你的print-helper可能生活在一个完全不同的模块中,并且有一个完全不同的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 

实际上,大多数人只想将自己的doc字符串作为参数传递给它,但是被调用的辅助函数可以单独查找它。我在我的unittest代码中使用它,这有时很方便填写一些日志或使用doc字符串作为测试数据。这就是为什么所提出的get_caller_doc()只查找测试类的全局测试函数和成员函数的原因,但我想这对于大多数想要了解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)

使用sys._getframe(1)定义正确的get_frame_doc(frame)留给reader()。

答案 6 :(得分:1)

这样做有一个简单的方法,没有人提到过:

import inspect

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

这就是你想要的。

这里没有什么花哨的东西。所发生的一切都是,在函数中执行func.__doc__会延迟属性解析,以便在其上查找__doc__,就像您期望的那样。

我将它与docopt用于控制台脚本入口点。

答案 7 :(得分:0)

插入 print __doc__def __init__之前的类声明之后,每次使用类启动对象时,都会将doc字符串打印到控制台