2016-09-23 36 views
1

私は内部で別の関数を再帰的に実行する関数を持っており、その関数のすべての実行に対して変数を共有します。そのようなPythonは関数内の関数のグローバル変数を共有します

何か:

def testglobal(): 
    x = 0 
    def incx(): 
    global x 
    x += 2 
    incx() 
    return x 
testglobal() # should return 2 

しかし、私は取得していますエラーNameError: name 'x' is not defined

リストを作成し、xとしてそのリストの最初の値を使用するためのハックソリューションがあります。しかし、これはとても醜いです。

xincxと共有するにはどうすればよいですか?あるいは、私はまったく別のアプローチを使うべきですか?

+1

のpython 3では新しいキーワード、[非ローカル](https://docs.python.org/3/がありますreference/simple_stmts.html#the-nonlocal-statement)、これはあなたが望むものとまったく同じです。これはクロージャであるため、変更なしで 'x'にアクセスできますが、' incx'の中に 'x = 1'を代入すると' xx'が 'incx'にローカルになり、したがって同じものを参照しません変数。 「非ローカル」はこれを達成する。 – alexpeits

答えて

1

xにアクセスするには、nonlocalステートメントを使用します.testglobalでは、グローバルではありませんが、ローカルではありません。

def testglobal(): 
    x = 0 
    def incx(): 
    nonlocal x 
    x += 2 
    incx() 
    return x 
assert 2 == testglobal() 

あなたは、Python 2でこれを行うに来ることができる最も近い

は、あなたの質問に記載された引数に似た可変値、ハックと xを交換することです。

def testglobal(): 
    x = [0] 
    def incx(): 
    x[0] += 2 
    incx() 
    return x[0] 
assert 2 == testglobal() 

ここでは、リストの代わりに関数属性を使用する例を示します。

def testglobal(): 
    def incx(): 
    incx.x += 2 
    incx.x = 0 
    incx() 
    return inc.x 
assert 2 == testglobal() 
+0

しかし、これはPython 3でのみ導入されました。しかし、このコンセプトは非常によく見えます、どのようにPython 2で同じことをするのですか? –

+0

mutable-argument hackが足りないことはありません。クロージャーは読み込み用の変数の値だけをキャプチャします。値を非言語的に変更することはできません(これがPython 3が 'nonlocal'キーワードを追加した理由です)。 – chepner

3

あなたはまだPythonの2.xのを使用していない限り、これは動作します:

def testglobal(): 
    x = 0 
    def incx(): 
    nonlocal x 
    x += 2 
    incx() 
    return x 

testglobal() # should return 2 

可能なクリーナーソリューションは、しかし、メソッド呼び出しの間、あなたの状態を保存するためのクラスを定義することです。

2

のでincxtestglobalからx変数を使用しますが、nonlocalステートメントを使用します。

def testglobal(): 
    x = 0 
    def incx(): 
     nonlocal x 
     x += 2 
    incx() 
    return x 

testglobal() 
関連する問題