Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 关于UnboundLocalError的混淆:局部变量';数字和';手动应用装饰器时在分配之前引用_Python 3.x_Recursion_Scope_Closures_Python Decorators - Fatal编程技术网

Python 3.x 关于UnboundLocalError的混淆:局部变量';数字和';手动应用装饰器时在分配之前引用

Python 3.x 关于UnboundLocalError的混淆:局部变量';数字和';手动应用装饰器时在分配之前引用,python-3.x,recursion,scope,closures,python-decorators,Python 3.x,Recursion,Scope,Closures,Python Decorators,正在试验使用标准python@decorator表示法将memoization decorator应用于递归函数,该表示法运行良好。根据我阅读的大部分文档,这些代码示例应该是等效的: # letting python decorator mechanism take care of wrapping your function with the decorator function @decorator def func(): . . . print(func(arg)) 及 然而,当我这样

正在试验使用标准python@decorator表示法将memoization decorator应用于递归函数,该表示法运行良好。根据我阅读的大部分文档,这些代码示例应该是等效的:

# letting python decorator mechanism take care of wrapping your function with the decorator function
@decorator
def func(): . . .

print(func(arg))

然而,当我这样做时,我在func上得到一个UnboundLocalError

如果我把代码改成

new_name = decorator(func)
print(new_name(func))
代码运行,但decorator只应用于第一个调用,而不应用于任何递归调用(这一点我并不感到惊讶),但我也没有收到任何错误消息

然而,我觉得奇怪的是原始错误消息本身。 如果我进一步试验并尝试以下代码:

new_name = decorator(func)
func = new_name
print(func(arg))
我在同一行上得到与以前相同的错误(????) 事实上,如果我形成了一个由这些赋值组成的链式结构,那么
func=multi\u names\u之后
我仍然在原始行中得到相同的错误 有人能解释一下发生了什么,为什么我会得到这个错误,为什么这个错误似乎与所讨论的变量的位置断开了连接

根据要求,这里是大部分实际代码(仅包含一个递归函数),希望不要太多

import functools 
 
def memoize(fn): 
  cache = dict() 

  @functools.wraps(fn) 
  def memoizer(*args):
    print(args)
    if args not in cache: 
      cache[args] = fn(*args) 
    return cache[args] 
 
  return memoizer

#@memoize   
def number_sum(n): 
  '''Returns the sum of the first n numbers''' 
  assert(n >= 0), 'n must be >= 0' 
  if n == 0:
    return 0
  else:
    return n + number_sum(n-1)

def main():
  # Book I'm reading claims this can be done but I get error instead:
  number_sum = memoize(number_sum) # this is the flagged line
  print(number_sum(300))
  #UnboundLocalError: local variable 'number_sum' referenced before assignment

  # When I do this instead, only applies decorator to first call, as I suspected
  # but works otherwise: no errors and correct - but slow - results
  # No complaints about number_sum
  wrapped_number_sum = memoize(number_sum)
  print(wrapped_number_sum(300))

  # This is what is odd:  
  # When I do any version of this, I get the same error as above, but always on
  # the original line, flagging number_sum as the problem
  wrapped_number_sum = memoize(number_sum) # the flagged line, no matter what
  number_sum = wrapped_number_sum
  print(number_sum(300))

  OR even:
  wrapped_number_sum = memoize(number_sum) # still the flagged line
  another_variable = wrapped_number_sum
  number_sum = another_variable
  print(number_sum(300))

if __name__ == '__main__': 
  main()


我对此感到有点困惑。

“但装饰器只应用于第一个调用,而不应用于任何递归调用”-这对我来说是有意义的,因为装饰器被分配给了一个不同的命名[可能]局部变量,与任何递归用法无关。无论如何,发布完整代码(作为最小复制案例)导致UnboundReferenceError。该函数可能不在同一范围内声明。这段代码实际上也应该与报告的错误相匹配,然后逐字报告。谢谢,我会这样做的。我预期第一个结果(它不会应用于递归调用),但我没有预料到错误。“但是装饰器只应用于第一个调用,而不应用于任何递归调用”-这对我来说是有意义的,因为装饰器被分配给不同的命名(可能)局部变量,与任何递归用法无关。无论如何,发布导致UnboundReferenceError的完整代码(作为最小复制案例)。该函数可能不在同一范围内声明。这段代码实际上也应该与报告的错误相匹配,然后逐字报告。谢谢,我会这样做的。我预期第一个结果(它不会应用于递归调用),但我没有预料到错误。
import functools 
 
def memoize(fn): 
  cache = dict() 

  @functools.wraps(fn) 
  def memoizer(*args):
    print(args)
    if args not in cache: 
      cache[args] = fn(*args) 
    return cache[args] 
 
  return memoizer

#@memoize   
def number_sum(n): 
  '''Returns the sum of the first n numbers''' 
  assert(n >= 0), 'n must be >= 0' 
  if n == 0:
    return 0
  else:
    return n + number_sum(n-1)

def main():
  # Book I'm reading claims this can be done but I get error instead:
  number_sum = memoize(number_sum) # this is the flagged line
  print(number_sum(300))
  #UnboundLocalError: local variable 'number_sum' referenced before assignment

  # When I do this instead, only applies decorator to first call, as I suspected
  # but works otherwise: no errors and correct - but slow - results
  # No complaints about number_sum
  wrapped_number_sum = memoize(number_sum)
  print(wrapped_number_sum(300))

  # This is what is odd:  
  # When I do any version of this, I get the same error as above, but always on
  # the original line, flagging number_sum as the problem
  wrapped_number_sum = memoize(number_sum) # the flagged line, no matter what
  number_sum = wrapped_number_sum
  print(number_sum(300))

  OR even:
  wrapped_number_sum = memoize(number_sum) # still the flagged line
  another_variable = wrapped_number_sum
  number_sum = another_variable
  print(number_sum(300))

if __name__ == '__main__': 
  main()