2012-08-22 46 views
3

我有以下的装饰用的参数:的蟒蛇装饰变量的作用域 - 改变参数

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

+0

[Python变量作用域问题]的可能重复(http://stackoverflow.com/questions/370357/python-variable-scope-question) – delnan

+0

请参阅http://stackoverflow.com/questions/8447947/is-it - 可以在python中修改变量 - 但不是全局的sc – Dougal

回答

6

由于您将p分配到wrapper之内,因此Python将p作为wrapper的本地wrapper。在Python 3中,您可以使用nonlocal pp标记为从外部作用域引用。在Python 2中,虽然可以通过将关键字参数作为关键字参数传递给嵌套函数(例如,def decorator(fn, p=p))来获取对相同值的引用,但无法分配给中间p。

但是,目前还不清楚你在这方面得到了什么。 p已经只在pdecor的本地。 pdecor以外的任何代码都不能访问p,因此递减它不会对别处的任何代码产生任何影响。所以不管你是否可以递减p,它都不会真的完成任何事情。

+0

最初我想写一个“重试”装饰器,它重试运行函数给定的次数。所以我会尝试运行'fn'并将'p'递减''fn'引发异常,直到我退出'p'重试或'fn'成功为止。 但是现在我很高兴,Python不让我这样做,否则所有执行装饰函数将共享相同的重试计数器,对吧? –