5

パラメータ付きの次のデコレータがあります。

from functools import wraps
def pdecor(p):
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            p -= 1
            return fn(*args, **wargs)
        return wrapper
    return decorator

デコレータを使用しようとすると、次の結果になります。

>>> @pdecor(1)
... def run(): pass
...
>>> run()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in wrapper
UnboundLocalError: local variable 'p' referenced before assignment
>>>

を変更できないのはなぜpですか?

4

1 に答える 1

9

あなたがpinsideに割り当てるのでwrapper、Pythonはpinsideを。wrapperのローカルとして扱いwrapperます。Python 3では、外部スコープから参照されているものとしてnonlocal pマークを付けるために使用できます。pPython 2では、中間のpに割り当てる方法はありませんが、同じ値への参照をキーワード引数(たとえばdef decorator(fn, p=p))として入れ子関数に渡すことで取得できます。

ただし、とにかくこれで何をしているのかは明確ではありません。 pはすでにローカルのみpdecorです。外部のコードpdecorはアクセスできpないため、デクリメントしても他のコードには影響しません。したがって、デクリメントできるかどうかにかかわらpず、実際には何も達成されません。

于 2012-08-22T17:27:12.393 に答える