Python 的 for 和 while 循环为什么没有引入新的作用域?

2020-08-04 09:25:56 +08:00
 CNife

C 家族的编程语言,基本都会为 for 和 while 循环引入新的作用域,以保证循环里定义的局部变量不会污染外部作用域。

for (int i = 0; i < 10; i++) {
    printf("%d\n", i);
}
// 无法再访问 i

但 Python 不是这样,for 和 while 循环内的局部变量会在循环后继续保留,依然可以被访问。也就是说,for 和 while 循环没有引入新的作用域。

for i in range(10):
    print(i)
print(i) # 可以访问,i=9

很明显,这样的做法会造成很多不必要的错误,比如循环内的变量遮盖了外部作用域的变量,循环结束后使用了被循环污染的变量等。

Python2 有这样的问题可以归结为历史原因,Python3 为什么也继承了这个问题?

4985 次点击
所在节点    Python
38 条回复
0312birdzhang
2020-08-04 09:34:14 +08:00
这就是 Python.jpg
domosekai
2020-08-04 09:34:23 +08:00
解释语言的锅?
zachlhb
2020-08-04 09:36:52 +08:00
变量名不要起成一样的
sixway
2020-08-04 09:37:16 +08:00
https://mail.python.org/pipermail/python-ideas/2008-October/002124.html
这里可以看见,应该是因为闭包的问题
optional
2020-08-04 09:39:48 +08:00
函数作用域是很多语言的特性啊,比如 c89 es5
infun
2020-08-04 09:40:11 +08:00
我记得之前查过说 因为 for 循环不是函数体,所以这里的变量与 for 是同级的,所以注意命名吧
youthfire
2020-08-04 09:40:23 +08:00
没有学过其他语言,所以我的作法是一段代码封装一个函数就隔离了
DOLLOR
2020-08-04 09:42:16 +08:00
js 的 var 声明也是这样的,是函数级作用域,会提升到函数开始处,不过后来有了 let 和 const 这两,用来声明块级作用域,不再有这种问题了。
magiclx
2020-08-04 09:56:55 +08:00
其实 for 循环结束后,如果你想知道 i 最后的值,能访问到 i 没什么不好的。
其实是需要养成一个习惯,如果后面新使用 i 时,必须赋初始值。
xiaolinjia
2020-08-04 10:01:00 +08:00
你这个问题确实是这样的,所以我一般用列表推导,就没这个问题( Py3 限定)
[i for i in range(10)]
print(i)
NameError: name 'i' is not defined
laike9m
2020-08-04 10:08:03 +08:00
其实就是语言没设计好。。
Vegetable
2020-08-04 10:12:39 +08:00
设计就是设计,这个设计并没有带来什么真正的问题,不像 js 的 var 一样反认知。
qdzzyb
2020-08-04 10:16:45 +08:00
这个还好吧 也没规定 for 一定要开启一个作用域吧
msg7086
2020-08-04 10:17:10 +08:00
因为他是 Python,他不是其它语言。
而且 C++之前的 for 循环声明的变量也是会算在外作用域的,后来规范里明确要求放进内部作用域,才改成了现在这样。
whoami9894
2020-08-04 10:22:59 +08:00
Python 只有 def, class, lambda, [i for i ...]会引入新作用域
CNife
2020-08-04 10:24:38 +08:00
@magiclx 是这样的,但就像一个圆桌子上吃饭,别人都是右手,就你 Python 非要拿左手吃饭一样,硌人。
yzqtdu
2020-08-04 10:26:39 +08:00
这个问题我找到[一篇博客]( https://eli.thegreenplace.net/2015/the-scope-of-index-variables-in-pythons-for-loops/)
这应该是语言的设计问题,前阵子看的 plp 刚好讲了 for 循环的语义复杂性,不光有 index 的访问问题,还有循环体内修改 index 和结束标记的问题
est
2020-08-04 10:31:33 +08:00
循环都是单字母变量。如果你污染外边的「作用域」了说明你单字母变量是不是太多了? 23333333333
vagrantear
2020-08-04 11:47:35 +08:00
为什么别人设计的语言一定要遵循你的想法呢,你还能指望每个语言都一模一样?
Ehend
2020-08-04 11:49:57 +08:00
这就是我放弃 Python 的原因,但也方便不少,不喜欢就换 Java 或者 c++吧。ps:已经换 c++。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/695413

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX