【问题标题】:Local variable referenced before assignment - error赋值前引用的局部变量 - 错误
【发布时间】:2020-05-28 06:15:05
【问题描述】:

这个函数应该给以列表形式给出的数字加 1。 如果列表是[1, 2, 3],那么这个函数应该返回[1, 2, 4],因为123 + 1 == 124

下面是有问题的函数:

def plusOne(self, A):
    val = 1;
    for i in range(len(A)-1,0,-1):
        val = val + A[i]
        borrow = int(val/10)
        if borrow == 0:
            A[i] = val
            break;
        else:
            A[i] = val%10
            val = borrow
    A = [borrow] + A
    while A[0]==0:
        del A[0]
    return A

错误信息是:

Traceback (most recent call last):
  File "main.py", line 225, in 
    Z = obj.plusOne(A)
  File "/tmp/judge/solution.py", line 8, in plusOne
    A = [borrow] + A
UnboundLocalError: local variable 'borrow' referenced before assignment

令人惊讶的是,下面的代码运行时没有任何错误:

class Solution:
    # @param A : list of integers
    # @return a list of integers
    def plusOne(self, A):
        val = 1;
        for i in range(len(A),0,-1):
            val = val + A[i-1]
            borrow = int(val/10)
            if borrow == 0:
                A[i-1] = val
                break;
            else:
                A[i-1] = val%10
                val = borrow
        A = [borrow] + A
        while A[0]==0:
            del A[0]
        return A

我还是不明白,如果直接在循环内部初始化借用变量会导致错误,那么上面的 sn-p 也应该抛出错误,对吧?

【问题讨论】:

  • 此函数似乎与某个类无关,如果不是,请尝试删除 self 参数。
  • 如果for 循环没有执行,就会发生这种情况——因此borrow 从未在其中初始化。你用什么来调用这个函数?

标签: python python-3.x list


【解决方案1】:

borrow 在for 循环中被声明/初始化。

for i in range(len(A)-1,0,-1):

如果 len(A) 为 1,那么将不会有任何范围可以循环,并且借用永远不会进入范围,因此会出现错误。

【讨论】:

    【解决方案2】:

    您面临的问题是范围界定的经典问题。

    变量borrowfor循环之前没有定义,代码尝试在循环之后访问它。

    如果len(A) > 1,您的代码将完美运行,因为在这种情况下borrow 是在循环中定义的并且正在执行循环。

    但是,如果是len(A) <= 1,在这种情况下,代码会直接尝试访问变量borrow,这是以前从未定义过的。

    在这种情况下,最佳做法是使用默认值定义变量。 在这种情况下,borrow = 0 将是正确的值,如果您在 for 循环之前定义它。

    我希望这会有所帮助:)

    【讨论】:

      【解决方案3】:

      您的代码几乎没有问题。在大多数情况下,它确实按预期工作。请允许我提出一些改进建议并指出问题。

      首先,您的代码中有两个分号,它们在 Python 中是不需要的。 (line 2) val = 1;(line 8) break;

      其次,当列表被发送到方法和函数时,它们作为引用发送,因此,这些方法内部的更改将应用​​于原始列表。

      第三,循环中的中断通常表明错误的选择和计划。

      第四,如果plusOne 不是类的一部分,则不需要self,因为它是参数(如果它是类的一部分,则将其留在那里并在调用时使用self.plusOne(..) 调用。

      从不同的角度来看,我会这样做:

      def plusOne(self, lst):
          if len(lst) > 0:
              # Initial value to increase by
              val = 1
              # Initialization of list index to last element.
              i = -1
              # Calculate the number after addition, calculate the borrow and replace in the list.
              num = val + lst[i]
              borrow = num // 10
              lst[i] = num % 10
              # While there is any borrow and the list didn't read the first element.
              while borrow != 0 and i > len(lst)*-1:
                  # Update the borrow to new value.
                  val = borrow
                  # Decrease the index.
                  i -= 1
                  # Calculate the number after addition, calculate the borrow and replace in the list.
                  num = val + lst[i]
                  borrow = num // 10
                  lst[i] = num % 10
      
              # Check if borrow remaining after index out of range.
              if borrow != 0:
                  # Insert borrow before the first element.
                  lst.insert(0, borrow)
              # Remove leading zeros.
              while lst[0] == 0:
                  del lst[0]
      
      
      def main():
          lst = [1, 2, 9]
          plusOne('', lst)
          print(lst)
      
      
      if __name__ == '__main__':
          main()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-02
        • 2011-11-06
        • 2018-01-12
        相关资源
        最近更新 更多