factorial
最初の例ではグローバル関数です。再帰的に呼び出すという事実は、それを呼び出すために関数オブジェクトを最初に検索する必要があることに変わりはありません。
つまり、現在呼び出されている関数は特別なものではありません。factorial
は依然として逆参照する必要がある名前であり、その名前が実行中の関数を参照していても問題ありません。
したがって、factorial
代わりにメソッドである 2 番目の例では、そのメソッドへのグローバル参照はありません。代わりに、参照を通じて、クラスの他のメソッドと同じように見つけることができますself
。
関数を定義すると、Python はその新しい関数オブジェクトへの参照を、指定した名前で現在のスコープに格納します。グローバル スコープでは、関数オブジェクトにバインドされdef foo()
たグローバル名になることを意味します。その名前を削除すると、再帰を中断foo
できます。
>>> def foo(): return foo() # infinite recursion
...
>>> def foo(): return foo() # infinite recursion
...
>>> foo
<function foo at 0x108e4b500>
>>> bar = foo
>>> del foo
>>> foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> bar
<function foo at 0x108e4b500>
>>> bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
NameError: global name 'foo' is not defined
ここに注意してNameError
ください。グローバル名前空間から削除しましたが、呼び出し可能foo
な参照が に残っていbar
ます。しかし、関数自体は、実行時にグローバル名を見つけることができませんfoo
。
それ以外の場合、Python 関数はそれ自体への参照を持ちません。関数内から、関数オブジェクト自体を確実に取得することはできません。あなたができる最善のことは、元の関数名を取得することです:
>>> def foo():
... return sys._getframe(0).f_code.co_name
...
>>> foo()
'foo'
>>> bar = foo
>>> bar()
'foo'
ただし、その名前でその関数オブジェクトに引き続きアクセスできるという保証はありません。