Python命名遮蔽困惑

3 投票
1 回答
8019 浏览
提问于 2025-04-18 00:30

我有一些代码,类似于这个(这段代码虽然没什么用,但能复现我的问题):

def fn():
    l = ["foo", "bar", "baz"]
    print map( lambda f : len(f), l )
    for i, f in enumerate(l):
        print i, f

然后,PyCharm 提示我说我声明的 lambda f “遮蔽了外部作用域的名字 f”。这似乎是因为在接下来调用 enumerate() 的时候,变量被重复使用了。

这段代码的运行结果是正常的,但这里到底发生了什么呢?我是不是可以理解为 Python 认为 ffn 里的一个局部变量,并警告我在 lambda 里面使用的 f 和本地定义的 f 不会是同一个变量——即使 lambda 里先用的是变量名 f 呢?

除了重命名变量,还有没有什么好的做法来避免这种情况?或者在这种情况下,我是不是可以凭自己的判断忽略这个警告?

1 个回答

1

在函数的定义中,只要你给一个变量赋值,这个变量就会变成函数内部的局部变量。举个更常见的例子:

x = 3
def foo():
    print x
    x = 2
foo()

当你定义了一个叫 foo 的函数时,如果里面有 x = 2 这行代码,而之前没有写 global x,那么 x 就会成为这个函数的局部变量。当你调用 foo 时,局部变量 xprint x 被调用时还没有定义,这样就会出现一个叫 UnboundLocalError 的错误。即使外面有一个同名的全局变量,这也没关系。

在你的例子中,for 循环实际上是对变量 f 的一种隐式赋值,所以 f 只在 fn 函数内部有效。这个警告是告诉你,当你要计算 len(f) 时,lambda 里的参数 f 会优先于 fn 函数内部的 f 的值。

撰写回答