【问题标题】:How to fix an UnboundLocalError caused due to a recursive function call in Python?如何修复由于 Python 中的递归函数调用导致的 UnboundLocalError?
【发布时间】:2015-02-13 07:56:58
【问题描述】:

我尝试将 CLRS 算法简介中给出的最大子数组问题的伪代码转换为 Python 中的完整工作代码。

代码:

def cross(A,low,mid,high):
    left_sum = -float("inf")
    s = 0
    i = mid

    while (i >= low):
        s = s + A[i]
        if s > left_sum:
            left_sum = s
            max_left = i
        i = i - 1

    right_sum = -float("inf")
    s = 0
    j = mid + 1

    while (j < high):
        s = s + A[j]
        if s > right_sum:
            right_sum = s
            max_right = j
        j = j + 1

    return (max_left,max_right,left_sum+right_sum)

def maxSubarray(A,low,high):
    if high == low: return (low,high,A[low])
    else:
        mid = (low+high)/2
        (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
        (right_low,right_high,right_sum) = maxSubarray(A,mid+1,high)
        (cross_low,cross_high,cross_sum) = cross(A,low,mid,high)

        if (left_sum >= right_sum & left_sum >= cross_sum):return (left_low,left_high,left_sum)
        elif (right_sum >= left_sum & right_sum >= cross_sum):return (right_low,right_high,right_sum)
        else: return (cross_low,cross_high,cross_sum)
t = [13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]

print maxSubarray(t,0,16)

当我尝试运行时,出现此错误。

错误:

Traceback (most recent call last):
  File "/home/suyash/Downloads/python/max_subarray.py", line 64, in <module>
    print maxSubarray(t,0,16)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 49, in maxSubarray
    (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
  File "/home/suyash/Downloads/python/max_subarray.py", line 53, in maxSubarray
    (cross_low,cross_high,cross_sum) = cross(A,low,mid,high)
  File "/home/suyash/Downloads/python/max_subarray.py", line 39, in cross
    return (max_left,max_right,left_sum+right_sum)
UnboundLocalError: local variable 'max_right' referenced before assignment

我该如何解决这个问题?我哪里出错了?

【问题讨论】:

  • 有问题的变量是在 if 语句中赋值的;只需确保在 if 语句 before (和外部)为它分配一个默认值。 max_left 也是如此,顺便说一句。

标签: python algorithm divide-and-conquer clrs


【解决方案1】:

两个非常小的错误:

  1. 您的列表,即t 的长度为16。这意味着最后一个索引是15。因此调用maxSubarray(t,0,15) 而不是maxSubarray(t,0,16)
  2. while (j &lt;= high)。循环直到j&lt;= high 直到j&lt;high

此外,通过这两个修复,您无需将任何默认值设置为 max_rightmax_rightwhile 任何 if 条件在每个递归调用中都将始终为 True。

演示:

>>> def cross(A,low,mid,high):
...     left_sum = -float("inf")
...     s = 0
...     i = mid
...     while (i >= low):
...         s = s + A[i]
...         if s > left_sum:
...             left_sum = s
...             max_left = i
...         i = i - 1
...     right_sum = -float("inf")
...     s = 0
...     j = mid + 1
...     while (j <= high):  # Loop until j<= high not until j<high
...         s = s + A[j]
...         if s > right_sum:
...             right_sum = s
...             max_right = j
...         j = j + 1
...     return (max_left,max_right,left_sum+right_sum)
... 
>>> def maxSubarray(A,low,high):
...     if high == low: return (low,high,A[low])
...     else:
...         mid = (low+high)/2
...         (left_low,left_high,left_sum) = maxSubarray(A,low,mid)
...         (right_low,right_high,right_sum) = maxSubarray(A,mid+1,high)
...         (cross_low,cross_high,cross_sum) = cross(A,low,mid,high)
...         if (left_sum >= right_sum & left_sum >= cross_sum):return (left_low,left_high,left_sum)
...         elif (right_sum >= left_sum & right_sum >= cross_sum):return (right_low,right_high,right_sum)
...         else: return (cross_low,cross_high,cross_sum)
... 
>>> t = [13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7]
>>> print maxSubarray(t,0,15)  # Last index = 15 not 16
(7, 10, 43)  # This shows max subarray is from index 7 to 10 i.e., [18,20,-7,12] and the sum is 43

【讨论】:

  • 是的,这非常有效。谢谢你。不过还有一个问题。当我刚刚运行 cross 函数时,代码print cross(t,0,8,16) 可以正常工作而不会出现任何错误。为什么会这样?
  • 您在第一次递归调用 (0,8,16) 时没有收到错误,但在第 4 次即第 2 次调用 -> (0,4,8),第 3 次调用 -> (0,2,4),第 4 次调用 -> (0,1,2)。在这次通话中,您有 j=mid+1 即 = 2 并且 while (j &lt; high)False,因为 2False。所以max_left 没有设置,你会得到一个错误。
【解决方案2】:

你忘了考虑边界条件。

通常情况下成功的条件可能会突然失败,从而使变量未绑定。无论如何,您都需要确保该变量具有合理的默认值。

【讨论】:

    【解决方案3】:

    您只在while 循环内的if 语句中分配max_right,这意味着如果您遇到异常,那么s &gt; right_sumj &lt; high从不为真:

    while (j < high):
        s = s + A[j]
        if s > right_sum:
            right_sum = s
            max_right = j
        j = j + 1
    

    你应该给max_right一个默认值while循环之外max_right = high 在这里比较合适。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-11
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多