智能决策上手系列教程索引
下划线_是很神奇的一个符号, 在 Python 里有很多特殊作用.
表示刚才输出的内容
用下划线表示最近一次输出的内容, 这个在很多教程问答中出现, 请认真看下面这个:
image.PNG
使用 python3 命令进入 python 的解释器状态:
第一行输入 s='a,b,c,d'然后就回车第二行输入_, 报错 not defined 未定义, 说明刚才什么也没输出(不是吗?).
然后输入单个的 s 回车, 输出了字符串'a,b,c,d', 然后再执行 s.split(',')用逗号分割成为列表, 成功!
然后输入 a=99, 再换行输入_, 得到的仍然是刚才输出的列表(不是字符串啦!)
再输入 a, 回车输出
99
, 这也把'_'变成了
99
, 然后 + 1 就会累加上去.
后来我们又创建了列表 c, 并输出它, 也就指定到了_, 并且可以使用_[0:1]取得第一个元素, 说明下划线不仅仅可以表示输出的字符串和数字, 还可以是更复杂的东西.
注意: 这种用法只能在命令行中使用, 禁止在. py 文件或者 Notebook 中使用.
"我不在乎这个东西"
下划线还可以当做毫无意义的占位符号, 比如 for 循环的格式是 for n in range(0,100): 这里的 n 有些时候根本没有用, 但又不能省略, 那么就可以用下划线鄙视它一下:
- for _ in range(10):
- print('哈')
这里只是大笑十声, 那么如果用 n 也毫无用处, 但是下面这个情况就还是需要 n 的:
- for n in range(10):
- print('第'+str(n)+'声大笑')
这个用法可以扩展到元组构成的列表:
- li=[('a',99),('b',100)]
- for _,v in li:
- print(v)
输出 99 和 100. 如果变成 for v,_ in li: 就会输出 a 和 b. 如果变成 for v in li 就会输出两个完整的元组 ('a',99) 和('b',100).
还有一些其他情况也可以用下划线表示占位:
- a=(101,102,103,104,105)
- x,_,z,_,_=a
- print(x,z)
直接创建 xz 两个变量, 输出 101 和 103, 我们不在乎其他的.
下面是更厉害的占位:
- a = (101, 102, 103, 104, 105)
- x, *_, m = a
- print(x, m)
星号是乘法, 在这里就把中间的几个都占位了, 输出 101 和 105.
_abc 单下划线开头, 表示私有不被导出
单个下划线开头的名称只能在当前文件使用, 不能导出到其他文件调用.
比如下面的 gongkai 对象可以在被别的文件 import 这个文件后调用, 但_siyou 却不能被使用:
- #a.py 文件
- class gongkai():
- _hide=99
- vis=100
- def _hideMethod(self):
- print('...')
- def visMethod(self):
- print('>>',self._hide,self.vis)
- class _siyou():
- vv=88
- #b.py 文件
- from a import *
- print(gongkai)
- c=gongkai()
- print(c._hide,c.vis)
- c.visMethod()
- #print(_siyou)
把 a.py 和 b.py 放在一个文件, 命令行进入这个文件夹, 运行 python3 b.py 会发现 gongkai 的都能正常显示,_hide 的下划线根本没用, 一样可以输出. 但是整个_siyou 都不能使用了.
下划线开头的顶级名称会被 import 禁用. 但其他的下划线开头的名称作为私有, 这就只是一种惯例而已.
但其实 python 根本不存在私有这个概念的, 即使上面的__siyou 也可以通过 from a import __siyou 正常导入, 只是 * 星号会忽略它. 如果你再 a.py 里面添加一行__all__=['_siyou']那么 import * 之后,_siyou 可以用, gongyou 却不可以用了.
abc_ 下划线结尾, 只是避免和系统自带关键字重名
这也是一个惯例, 比如不能 from=100 因为 from 是关键字, 只能改为 from_=100(如果你非要坚持用 from 这个词的话).
再比如下面这个 s 类是对 str 字符串的扩展, 避免了 split 命名重复:
- class s(str):
- def split_(self):
- return 100
- aa=s('a,b,c')
- print(aa.split_(),aa.split(','))
输出 100 和 ['a', 'b', 'c'].
__abc 双下划线开头, 表示碾压子类同样的名称
上面我们用 s(str)扩展了 str 类, 避免了 split 方法混淆, 但如果真的混淆了, 那么该听谁的呢?
如果在 class a 里面使用了双下划线的名称开头, 那么不管以后怎么扩展, 都是它说了算, 比如:
- class A:
- __v=100
- v=200
- def p(self):
- print(self.__v,self.v)
- class B(A):
- __v=99
- v=199
- b=B()
- b.p()
- # 输出 100,199
输出 100 和 199.v 被子类 B 覆盖了, 但 A 把子类的__v 给碾压了.
abc 双下划线开头又结尾, 表示这是系统需要的功能
这样的名称一般不会用到, 但也不要去修改. 比如__init__用来初始化类.
gettext 的_是一个用于 I18N/l18n 的方法
I18N 就是 Internationalization(i+18 个字母 + n 组成)国际化; l 就是 Localization 本地化.
如果你 import getext 那么就会有下划线这个方法, 其实就是 gettext.gettext 的缩写.
1_000_000 分割数字, 相当于数字中的千分位逗号
a=1_000_000 就是 100 万, 1_0_0 就是 100.
来源: http://www.jianshu.com/p/64cf47b688f9