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

如何从函数本身内部打印python函数的Docstring?,python,function,printing,docstring,Python,Function,Printing,Docstring,我想从函数本身内部打印python函数的docstring。 例如 目前,我是在定义了我的_函数之后直接执行此操作的 print my_function.__doc__ 但我宁愿让函数自己做这件事 我已尝试调用print self.\uuuu doc\uuuuuprint self.my\u函数.\uuu doc\uuuu和打印此文件。\uu doc\uuuuu在我的\u函数中,但这不起作用。尝试: class MyClass(): # ... def my_function(

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

目前,我是在定义了
我的_函数之后直接执行此操作的

print my_function.__doc__
但我宁愿让函数自己做这件事

我已尝试调用
print self.\uuuu doc\uuuuu
print self.my\u函数.\uuu doc\uuuu
打印此文件。\uu doc\uuuuu
在我的\u函数中,但这不起作用。

尝试:

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

之后缺少一个冒号(
)此操作:

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()

名称错误:未定义全局名称“my_function”

您提出的问题像是类方法而不是函数。名称空间在这里很重要。对于函数,
print my_function.\uuuu doc\uu
可以,因为my_函数位于全局命名空间中

对于一个类方法,那么
打印self.my\u方法.\uuuuu doc\uuuu
将是一个不错的选择

如果您不想指定方法的名称,而是想向其传递一个变量,那么可以使用内置函数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 )
只要您不更改绑定到名称
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
)作为其第一个参数,因此它始终可以获得正确函数的docstring。如果在方法上使用,通常的
self
将成为第二个参数。

这应该有效(在我的测试中,它也包括输出)。你可能会用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。此外,这并不要求您知道类/方法/函数的名称

类、方法和函数的示例。如果不是你想要的,告诉我:)


如前所述,使用函数名是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__
如果要查找调用者的文档字符串,这无论如何都不会起作用,因为您的打印助手可能位于一个完全不同的模块中,该模块具有完全不同的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字符串作为参数传递,但是被调用的helper函数可以自己查找它。我在我的unittest代码中使用了它,有时它可以方便地填充一些日志或使用文档字符串作为测试数据。这就是为什么现在的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定义适当的get\u frame\u doc(frame).\u getframe(1)留给reader()。

有一个非常简单的方法,但还没有人提到:

import inspect

def func():
    """Doc string"""
    print inspect.getdoc(func)
这就是你想要的

这里没有什么稀奇古怪的事。所发生的一切是,通过在函数中执行
func.\uuuuu doc\uuuuu
延迟属性解析足够长的时间,以便在其上查找
\uuuuuu doc\uuu
,正如您所期望的那样

我使用docopt作为控制台脚本入口点。

插入
print\uuuuu doc\uuuuuu

在类声明之后,
def\uu init\uuuuu
之前,每次使用类启动对象时,都会将文档字符串打印到控制台

对不起,伙计们,我的愚蠢自我。我的函数。\uu doc\uu实际上起作用。您的类方法只起作用,因为您以前在全局命名空间中将我的函数定义为函数。用一个新的python实例试试;)@你没有测试你的第二个代码片段。没有work@AlexLeach您是否使用类测试了代码段?事实上,它不起作用……@jgritty和alexleach。类中定义的id为est函数的方法无法知道它们的外部空间。看这个问题()和我对它的回答不,我没有,但我认为jgritty可能已经做到了。只是做了测试,它工作正常,正如预期的那样(更改方法的docstring,仍然打印函数docstring)。模块中定义的函数在类方法中可用。e、 g.如果类方法是在脚本顶部导入的,则无需在类方法中重新导入。有没有好的方法不必重复方法名称本身?像这样的东西。医生还是什么?对不起,我是python新手。是的,不是真的。。我通过dir(self.my_函数)和
self.my_函数查看了一下。self.my_函数看上去可能很有趣,但仍然需要通过该对象模型访问它。您可以为dir(MyClass)中的方法添加如下函数:
:如果hasattr(getattr(MyClass,method),“\uuu doc\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。我会把它放在我的原始答案中…@shane87,AlexLeach和Mattloungo:请看我的答案
 this is foo 
 this is bar 
None
None
 showing my 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)
import inspect

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