2

私はこのコードを持っています:

import re

def doReplace(toReplace):
    i = 1
    def chapterReplacer(_):
        result = 'Chapter %i' % i
        i += 1
        return result

    return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)

test = 'Chapter one Chapter Two Chapter three'
print doReplace(test)

実行すると、次のエラーが発生します。

Traceback (most recent call last):
  File "C:/Python26/replace.py", line 13, in <module>
    print doReplace(test)
  File "C:/Python26/replace.py", line 10, in doReplace
    return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
  File "C:\Python26\lib\re.py", line 151, in sub
    return _compile(pattern, 0).sub(repl, string, count)
  File "C:/Python26/replace.py", line 6, in chapterReplacer
    result = 'Chapter %i' % i
UnboundLocalError: local variable 'i' referenced before assignment

私はchapterReplacerがローカル変数iをキャプチャするという印象を受けましたが、それは起こっていないようですか?

4

4 に答える 4

6

いいえ、Python 2では、可変のトリックを使用せずに使用することはできません。

def doReplace(toReplace):
    i = [1]
    def chapterReplacer(_):
        result = 'Chapter %i' % i[0]
        i[0] += 1
        return result

    return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)

通常、Pythonは、ローカルに割り当てられていない場合にのみ、周囲のスコープで変数を探します。バイトコンパイラが直接割り当て(i = something)を確認global iし、それ以外の方法でそれを説得するステートメントがない場合、変数はローカルと見なされます。

iしかし、上記のコードでは、関数で割り当てることはありませんchapterReplacer。はい、変更しますi[0]が、リスト自体に格納されている値は変更されiません。

Python 3では、nonlocalステートメントを使用して、Pythonに変数のクロージャーを調べさせます。

def doReplace(toReplace):
    i = 1
    def chapterReplacer(_):
        nonlocal i
        result = 'Chapter %i' % i
        i += 1
        return result

    return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)
于 2012-06-15T20:02:58.280 に答える
2

i関数属性を作成できます

def doReplace(toReplace):
    chapterReplacer.i = 1
    def chapterReplacer(_):
        result = 'Chapter %i' % chapterReplacer.i
        chapterReplacer.i += 1
        return result

    return re.sub('Chapter [a-zA-Z]+', chapterReplacer, test)

編集: Python 3の時点で、nonlocal@MartijnPietersのソリューションを使用できます。

于 2012-06-15T20:03:19.557 に答える
2

Python では、関数内で変数に代入する場合 ( などの複合代入演算子を使用する場合でも)、 orステートメント+=で特に指定しない限り、その変数はローカルと見なされます。globalnonlocal

于 2012-06-15T20:05:21.687 に答える
1

コンパイラは、変数iが関数内で別の値を取得することを確認chapterReplacerすると、それをローカルとして扱い、「クロージャー マジック」は適用されません。行を削除するi += 1と、コードが実行されます。

于 2012-06-15T20:06:47.747 に答える