我刚学Python那会,看到别人代码里有下划线,总觉得很神秘。什么单下划线双下划线,什么前后都有下划线。当时就想,这东西到底干嘛用的。翻了不少资料,越看越糊涂。
直到有一天,我写了个小脚本。类里有个方法,本来只想内部用用。结果同事调用了,还把数据改了。程序直接崩了。从那会开始,我才认真琢磨下划线的意思。
先说单前导下划线,比如 _value。这东西不是强制性的,就是个约定。你告诉别人,这个变量或方法是内部用的,别乱碰。Python的解释器不会拦你,但大家看到这个符号,就会自觉点。我有个习惯,把不需要对外暴露的辅助函数名字前加个单下划线。这样队友看代码,一眼就知道哪些是“私货”。
再说双前导下划线,像 __value。这个就不一样了。Python会做名字重整。比如你在类里定义了个 __secret,外部用 obj.__secret 是拿不到的。它会变成 _ClassName__secret。这个机制能避免子类意外覆盖父类的属性。我曾踩过坑,定义了个 __data,子类也定义了 __data。结果各自调用各自的方法,数据没混。这一点在写框架或者库的时候特别好用。
前后都有双下划线,就是 __init__、__str__ 这种。这叫魔法方法,或者叫特殊方法。不是给你直接调用的。Python解释器会在特定场景自动调用它们。比如你打印一个对象,解释器就会找它的 __str__ 方法。我见过新手直接写 obj.__init__() 去初始化,那是错的。应该用类名加括号。魔法方法是被系统保留的,别自己乱发明这种名字格式。
单后置下划线,比如 class_。这个纯粹是为了避开关键字。你要用 class 这个名字,但 class 是保留字。那就写成 class_。简单直接,没有任何魔法。
这些规则理解了,写代码就舒服多了。有次我接手一个老项目,里面全是公开属性。改一个地方,别的地方跟着出问题。后来我重构,把所有内部状态都加上双前导下划线。外部调用就通过接口方法,数据安全多了。另一个项目里,我用单下划线标记那些暂未实现但准备以后改的方法。队友一看就知道,这部分还没稳定。
还有个小技巧。在循环里用一个不用的变量,比如 for _ in range(10)。下划线代表“我不在乎这个值”。这是约定俗成的写法,让读代码的人知道,循环的次数重要,但具体值不重要。
我记得有次面试,面试官问Python下划线的使用。我把这些心得一说,他点了点头。他说很多人用了三年还没搞明白。我想想也是,这些符号看起来不起眼,背后是Python设计者的巧思。它们是代码里的路标,告诉你什么可以动,什么别碰。要是早三年知道这些,我能少掉多少头发啊。
现在写Python,我看到别人代码里的下划线,就像看到老朋友一样。知道它在哪出现,就有对应的规矩要守。你也别急,慢慢用着用着就懂了。真懂了那天,你会发现代码变得干净多了。