「行儀の良い」デコレータで適切に機能するハードコードされたバージョンの場合。関数の後に宣言する必要があります。関数が後でリバウンドした場合、変更はここで更新されます。
def get_name_doc():
# global function # this is optional but makes your intent a bit more clear.
return function.__name__, function.__doc__
これは、デフォルトの引数の動作を悪用するという点で、かなり厄介なハックです。この関数が「初期化」された時点でバインドされている関数を使用し、関数が再バインドされた場合でもそれを記憶します。引数を指定して呼び出すと、興味深い結果が得られます。
def get_name_doc(fn=function):
return fn.__name__, fn.__doc__
動的なものはまだハードコーディングされていますが、True の引数で関数が呼び出されると更新されます。基本的に、このバージョンは指示された場合にのみ更新されます。
def get_name_doc(update=False):
global fn
if update:
fn = function
return fn.__name__, fn.__doc__
もちろん、これにもデコレータの例があります。
@decorator # applying the decorator decorator to make it well behaved
def print_name_doc(fn, *args, **kwargs):
def inner(*args, **kwargs):
print(fn.__doc__, fn.__name__) # im assuming you just want to print in this case
return fn(*args, **kwargs)
return inner
デコレータ デコレータ (少なくとも) を読む必要があります。ハードコーディングされていることに注意する必要があるため、(コレクションモジュールからの)NamedTupleソースを見てください。悲しいことに、名前付きタプルのコードはかなり奇妙です。これは、従来のコードではなく eval で使用される文字列形式ですが、非常にうまく機能します。これは最も有望なバリアントのようです。メタクラスでもこれを実行できる可能性があります。これにより、きれいなコードが得られますが、コーディングが必要な舞台裏に隠された厄介なものが発生します。このIDは反対することをお勧めします
モジュールの最後に次の行を追加するだけで、インスペクション/リフレクション/テンプレート/メタクラスに入るよりも簡単な方法があると思います。
help(<module>)
ここで、作業中のモジュールの名前 (文字列) です。または、変数 __name__ でさえ。複数のモジュールまたは個々のクラスで作業している場合、これは __init__.py ファイルでも実行できます。