这个 scope/block leak 我最初是在学 nim 时看到的: https://github.com/nim-lang/Nim/wiki/Nim-for-Python-Programmers#scoping
最开始我还不是很在意,直到之前接手老项目代码,我都快疯了:if..elif..else 里面藏着 n 个变量,然后在后面使用变量的代码是否能正常运行完全靠运气(当然有一些业务逻辑保证,但业务逻辑一直在变啊,能从静态分析阶段排除的问题非要等到运行时再确认,费时费力) 我之前一直用嵌套 function 的方式来创造 scope ,以达到隔离变量名、最小化变量生命周期的目的 (我经常纠结命名:xx_a 、xx_b, 有了 scope 我全叫它们 xx )
我觉得有两方面的缺失在 python 中
针对第 2 点,我所了解的其他大部分语言都有对应的设计
针对第 1 点,javascript 有 let ,lua 有 local ,上面列出的其他语言没这毛病; python 的 nonlocal 也不是针对这种情况的。
很少见网上有过相关讨论,所以好奇问下大家难道不在意吗?
-- 倒是找到个相关库: https://github.com/l74d/scoping
1
imycc 2022-08-07 12:04:04 +08:00
是有点在意的。块级作用域缺失,出现的 bug 靠编辑器发现不了。比如一个函数写得比较长,存在几个循环,后面的循环用错了变量之类的。
只能靠代码规范来规避了,比如控制函数长度,变量命名表意明确,临时变量的初始化、使用和销毁放到一块,写好注释之类的。 |
2
humiaozuzu 2022-08-07 12:07:44 +08:00
一方面是靠编码风格来减少这些 scope 在其他地方被引用。另外不知道 flake8 有没有插件可以发现这类用法, 提示出来
|
3
wxf666 2022-08-07 12:07:57 +08:00
这……是一个函数内揉了太多内容,还是不同含义的变量都用同一个命名表示了?
|
4
hezhiming1993 2022-08-07 14:46:56 +08:00
在意啊
所以转 Go 了, 现在小工具都用静态语言写 |
5
chenxytw 2022-08-07 18:39:28 +08:00
这点确实是 Why Python sucks 的重要组成部分。而且嵌套函数定义也确确实实就是唯一解决方案。
但其实 Python 作用域的坑远比你想象的深且大( 比如这个: https://blog.kevmod.com/2014/06/26/what-does-this-print-1/ |
6
junkun 2022-08-07 23:17:11 +08:00
我觉得 leak 这个名词不合适,python 它就是只有两种作用域,模块全局和函数内,并没有 leak 。global 和 nonlocal 其实只是变量查找的规则。
并且个人认为,python 其实设计上就不提倡嵌套函数(除非你要返回这个函数),过多的嵌套函数实际上就像共享全局变量一样,甚至 context 更复杂,也不好扩展。我更提倡在外面建一个新的函数然后把相关局部变量用参数传递进去,要修改 nonlocal 变量再返回出来。 |
8
haoliang OP 谢谢各位回复。
@chenxytw 哈哈,这个例子太冷门了,我目前没遇到过。不过帖子描述中的 nim 链接中确实有列出它。 @junkun 这 nonlocal 操作有点繁琐啊,看起来不贴近实际场景,我大概率会继续用 closure ,除非像 zig 这样不支持 nested function 更没有 closure 的。(为了区分这两者,就用 closure 、function 代替了) 我有些惊讶,lua 5.1 这个 10 来年语法没改变的语言在这点上都比 python 想得周到,而 python 这边竟然连个 pep 都没有。(lua 5.1 发布于 2006 ,python 3.0 于 2008 ) |