76

我想从函数本身内部打印 python 函数的文档字符串。例如。

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__and print this.__doc__,但这不起作用。

4

8 回答 8

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

只要您不更改绑定到 name 的对象,这将起作用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将成为第二个参数。

于 2012-01-11T19:57:20.333 回答
9

这应该有效(在我的测试中它确实有效,还包括输出)。您可能可以使用__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
于 2012-01-12T01:12:52.157 回答
6

这有效:

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”

于 2012-01-11T16:30:56.980 回答
4

有一个非常简单的方法可以做到这一点,但还没有人提到:

import inspect

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

这就是你想要的。

这里没有什么花哨的事情。正在发生的一切是,通过func.__doc__在函数中执行延迟属性解析足够长的时间,以便查找__doc__它可以按您期望的那样工作。

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

于 2017-01-11T13:27:55.403 回答
2

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

对于类方法,那么print self.my_method.__doc__将是要走的路。

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

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 )
于 2012-01-11T16:35:31.277 回答
2

正如多次提到的,使用函数名是在 globals() 目录中的动态查找。它仅适用于定义的模块并且仅适用于全局函数。如果你想找出一个成员函数的文档字符串,你还需要从类名中查找路径——这很麻烦,因为这些名字可能会很长:

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__

如果你想查找调用者的文档字符串,那无论如何都行不通,因为你的 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 

实际上,大多数人只希望自己的文档字符串作为参数传递下来,但是被调用的辅助函数可以自己查找所有内容。我在我的单元测试代码中使用它,有时这很方便填充一些日志或使用文档字符串作为测试数据。这就是为什么提供的 get_caller_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()。

于 2014-08-28T13:10:19.613 回答
1

尝试:

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

(*) 后面有一个冒号 ( :)my_function()

于 2012-01-11T16:22:51.200 回答
-1

print __doc__ 在类声明之后插入 ,在 , 之前def __init__,每次您使用该类启动一个对象时,都会将文档字符串打印到控制台

于 2017-03-08T18:06:06.800 回答