関数の内部から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__
を呼び出してみましたが、これは機能しませんでした。
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
と同様)を最初の引数として取得できるようになるため、常に適切な関数のdocstringを取得できます。メソッドで使用する場合、通常のself
が2番目の引数になります。
これは動作するはずです(私のテストでは、出力も含まれています)。おそらくgetdocの代わりに__doc__
を使用することもできますが、私はそれが好きなので、まさに私が使用したものです。また、クラス/メソッド/関数の名前を知る必要はありません。
クラス、メソッド、関数の両方の例。それがあなたが探していたものではない場合教えてください:)
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
これは動作します:
def my_function():
"""Docstring for my function"""
#print the Docstring here.
print my_function.__doc__
my_function()
in 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」が定義されていません
質問を関数ではなくクラスメソッドのように提示しました。ここでは名前空間が重要です。関数の場合、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 )
試してください:
_class MyClass():
# ...
def my_function(self):
"""Docstring for my function"""
print MyClass.my_function.__doc__
# ...
_
(*)my_function()
の後にコロン(_:
_)がありませんでした
何度も述べたように、関数名の使用は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__
呼び出し元の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()がグローバルテスト関数とテストクラスのメンバー関数のみを検索する理由ですが、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()に任されています。
誰もまだ言及していない、これを行うための非常に簡単な方法があります。
import inspect
def func():
"""Doc string"""
print inspect.getdoc(func)
そして、これはあなたが望むことをします。
ここでは何も変わっていません。起こっているのは、関数でfunc.__doc__
を実行することで、期待どおりに__doc__
を検索できるようになるまで属性解決を延期することです。
コンソールスクリプトエントリポイントのdocoptでこれを使用します。
クラス宣言の直後、print __doc__
の前にdef __init__
を挿入すると、クラスでオブジェクトを開始するたびにdoc文字列がコンソールに出力されます