【问题标题】:Python variable scoping in nested function calls嵌套函数调用中的 Python 变量作用域
【发布时间】:2022-11-27 04:57:19
【问题描述】:

我在 LeetCode 问题中来到这个code

class Solution:
    def maxProduct(self, root):
        self.res = total = 0

        def s(root):
            if not root: return 0
            left, right = s(root.left), s(root.right)
            self.res = max(self.res, left * (total - left), right * (total - right))
            return left + right + root.val

        total = s(root)
        s(root)
        return self.res % (10**9 + 7)

我将 self.res 更改为 res,如下所示

class Solution:
    def maxProduct(self, root):
        res = total = 0

        def s(root):
            if not root: return 0
            left, right = s(root.left), s(root.right)
            res = max(res, left * (total - left), right * (total - right))
            return left + right + root.val

        total = s(root)
        s(root)
        return res % (10**9 + 7)

并且代码中断为UnboundLocalError: local variable 'res' referenced before assignment。为什么res必须初始化为self.restotal不需要?

【问题讨论】:

  • 请使用您"change self.res to res" 的备用代码和相应的完整错误回溯更新您的问题,以帮助我们理解您的意思。
  • 是的,我认为在这种情况下,您将需要 def s(root): 内的 nonlocal res。 mCoding 的这个广泛的video 解释了 python 中的范围规则。

标签: python variables scope


【解决方案1】:

问题是嵌套函数s 有它自己的变量范围。 虽然它可以从封闭范围 (maxProduct) 读取变量 (如 res), 任何分配(例如res = max(...)) 将在s 的范围内引入一个变量,而不是 写入外部(res)。 因为在这种情况下maxProduct想要阅读修改的资源版本 s 生成的,使用了向 self 添加成员变量的技巧。 (在这种情况下,仅s对 self 的引用,然后添加一个成员,避免范围问题)。

请参阅这个小示例进行演示:

def foo():
        def bar():
                x=2
        x=1
        bar()
        return x

foo() 返回 1,而不是 2,因为 bar 中对 x 的赋值在 bar 的范围内引入了一个新变量

【讨论】:

    【解决方案2】:

    为什么 res 必须初始化为 self.res 而 total 不需要?

    它不是,而是因为 Python 的规则隐式声明, 默认赋值即声明.

    s来自total,它必然来自其他地方,但由于

     res = max(self.res, left * (total - left), right * (total - right))
    

    Python 将创建一个 res 变量,它是 s 的本地变量,因此您实际上有两个同名的不同变量,一个在 maxProduct 中,一个在 s 中。这称为shadowing

    您可以通过显式声明告诉 Python 一个被赋值的变量不是本地变量:

    nonlocal res
    

    这将使 Python 分配给该名称的词法最接近的变量:

    def foo():
        a = 1
        def bar():
            a = 2
        bar()
        print(a)
    
    foo()
    # 1
    
    def foo():
        a = 1
        def bar():
            nonlocal a
            a = 2
        bar()
        print(a)
    
    foo()
    # 2
    

    【讨论】:

      猜你喜欢
      • 2014-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-27
      • 2011-12-17
      • 2018-07-16
      • 1970-01-01
      相关资源
      最近更新 更多