1

Pythonの関数内の関数自体のスコープは何ですか? 私の質問は、最終的に再帰に挑戦することを考えたために発生します(ただし、私はそれを完全に理解するのに十分な能力はありません)。私は Eclipse (PyDev) をクラス内で使用しています。たとえば、次のようになります。

すべての本で広く使われている階乗の単純な再帰の例は次のとおりです。

def factorial(n):
       if (n==0):
           return 1
       else:

           return n*factorial(n-1)

別の例では、クラス内で次のようになります。

class test:

    def factorial(self,n):
       if (n==0):
           return 1
       else:
           return n*factorial(n-1)

使用する必要がありますself.factorial(n-1)か? (PyDev が未確認の変数を表示していないのに表示しているので、私はそうすべきだと思います)。この場合、オブジェクト自体への参照が必要なのはなぜですか? ここで理解しておくべき重要なことを見逃していますか?

4

4 に答える 4

2

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'

ただし、その名前でその関数オブジェクトに引き続きアクセスできるという保証はありません。

于 2013-10-24T18:01:32.970 に答える
1

これは再帰とは関係ありません。メソッドを定義する場合、またはクラス内のクラスを定義する場合でも、self関数に使用する必要があり、クラス内のクラスにはクラス名自体を使用する必要があります。実演してみましょう:

class Foo(object):

    def happy(self):
        print "Happy"

    def size(self, var):
        self.happy()  # You need to self to call happy
        if var == 1:
            return 1
        else:
            return 1 + self.size(var - 1)  # You need to refer to self

    class Bar:

        def __init__(self):
            super(Foo.Bar, self).__init__()  # You need to refer to Foo

クラス内の何かを参照するには、その名前空間を使用する必要があります。通常の関数を作成すると、ファイルの名前空間の一部になります。

于 2013-10-24T18:01:07.383 に答える
1

他の回答を補完するために、ここに簡単なデモがあります

def f():
   return f  # returning itself, but what does f resolve to?

# this is f
f
=> <function __main__.f>
# it is defined in the global scope
globals()['f']
=> <function __main__.f>
# when accessed from within itself, it is still itself
f()
=> <function __main__.f>
于 2013-10-24T18:03:36.903 に答える
0

再帰はプログラミング上の概念ですが、プログラミングの内部でも使用されます。

それを現実の世界に関連付ける:

再帰は、それ自体の内部にある何か自体への単なる参照です。たとえば、聞いたことがある頭字語は次のとおりです。

GNU Gnu は Unix ではない

頭字語の内部で頭字語が記述されているため、これは再帰的な頭字語です。ニワトリと卵のどちらが先かという興味深い形而上学的/哲学的議論につながる可能性があります。

プログラミング関連

正式な定義から抜け出すことができる場合は、関数のすべての呼び出しを関数のインスタンスと呼びましょう。

関数はコードで定義され、それ自体の内部で呼び出されます。

関数の定義はコードのインスタンスではありませんが、呼び出されると独自のインスタンスになります。インスタンス内では、他の関数を呼び出すことができます。たとえば、それ自体の内部でFunction(A)呼び出すことができます。Function(B)

再帰はちょうど whenFunction(B) = Function(A)であるため、それFunction(A)が再度呼び出されFunction(A)、既存のインスタンス内で の新しいインスタンスが開始されます。はコードの上に定義されているためFunction(A)、プロセッサはコードを再度呼び出すだけです。途中にある既存のインスタンスにはまったく依存しません。

そのため、recursion本当にどこにでも適用できます。

Google 検索のユーモラスな例で、再帰への自動修正が常に求められます

これは役に立ちましたか?

ハッピーコーディング!

EDIT:ああ、関数内で呼び出された関数のスコープは、それが呼び出された関数内にあるだけですFunction(A).calls Function(B)、つまり、Function(B)スコープは内にありFunction(A)ます。

于 2013-10-24T18:05:09.107 に答える