Py 乙己
孔乙己自己知道不能和架构师谈天,便只好向实习生说话。
有一回对我说道,“你写过Python么?”我略略点一点头。
他说,“写过代码,……我便考你一考。Python中的下划线,怎样用的?”
我想,搬砖一样的人,也配考我么?便回过脸去,不再理会。
孔乙己等了许久,很恳切的说道,“不能写罢?……我教给你,记着!这些用法应该记着。将来做面试官的时候要用。”
我暗想我和面试官的等级还很远呢,而且我们面试官也从不将这些问题拿来考应聘者;又好笑,又不耐烦,懒懒的答他道,“谁要你教,不就是命名变量,增加代码的可读性吗?”
孔乙己显出极高兴的样子,将两个指头的长指甲敲着键盘,点头说,“对呀对呀!……下划线有 x 种写法,你知道么?”
我愈不耐烦了,努着嘴走远。孔乙己刚用纸巾擦了擦键盘上的咖啡渍,想在IDE里写代码,见我毫不热心,便又叹一口气,显出极惋惜的样子。
正文
- 在交互式解释器中获取上一个语句执行的结果;
| 1+1 | 
- 用来在函数、模块、包、变量名中分隔单词,增加可读性;
| var_foo_bar = 'hello,world!' | 
- 内部使用的变量、属性、方法、函数、类或模块,(约定)又称为内部实现;
| # 假定存在foo.py中定义变量: | 
- 避免与 Python保留的关键字冲突(约定);
| Tkinter.Toplevel(master, class_='ClassName') # 注意class为Python内置关键字 | 
- 在类内的私有变量(private),类外部无法直接使用原名称访问,需要通过instance._ClassName__var的形式访问(name mangling);
| class Person(object): | 
我们可以使用dir(pi)看一下对象中的中的属性和方法:
| ['_Person__say_hello', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'get_age', 'get_name', 'name'] | 
这里 Python 解释器触发名称修饰,它这样做是为了防止变量在子类中被重写。
| # 新建一个集成Person的AI类 | 
我们可以看到继承关系:
| # 返回 | 
这点在 《Python Cookbook》- 8.5 在类中封装属性名 中对于单下划线和双下划线的使用场景也有提及和解释:
通常而言,你应该让你的非公共名称以单下划线开头。但是,如果你清楚你的代码会涉及到子类,并且有些内部属性应该在子类中隐藏起来,那么才考虑使用双下划线方案。
- 类里面的保护变量; - _var_ - 个人认为这个还是类内部使用变量的一种延伸用法,只不过在后面加下划线以做区分。但是,这个和双下划线会在一定程度上引起阅读混淆(如果眼神不好)。如果只是命名个别变量还是可以接受的。 
- Python内置的“魔法”方法或属性,你也可以自己定义,但 强烈不推荐。比如:
| __init__, __file__, __main__ | 
- 作为内部使用的一次性变量;
| # 通常在循环里使用,比如: | 
- i18n里作为- gettext()的缩写;
| _() | 
- 用来分隔数值以增加可读性(Python 3.6新增);
| >>> num = 1_000_000 | 
参考来源
- PEP 8 – Descriptive: Naming Styles
- Python basic cheatsheet
- The Meaning of Underscores in Python – dbader.org
- Python 中的下划线_有多少个意思?- 知乎
- Python 的类的下划线命名有什么不同? - 知乎
派森多一点
Python中的dunder
参见这里
关于
Python编程的一个尴尬的事情是:有很多种双下划线。 例如,语法糖下面的标准方法名称具有__getattr__这样的名称,构造函数是__init__,内置运算符可以用__add__重载,等等。 在Django框架中(至少在他们整合了magic-removal分支之前),对象关系映射器使用了名为user__id__exact的关键字参数。
双下划线的问题是很难向别人描述。 你怎么读__init__? “下划线下划线init下划线下划线”? “双下划线init双下划线”? 简单的 “init” 似乎漏掉了一些重要的东西。
我有一个解决方案:双下划线应该发音为 “dunder” 。 所以__init__念成“dunder init dunder”,或者也可以简读为 “dunder init” 。
现在我期待某个人定义一下 “dunderhead” 是什么意思,haha……







