-
名称前的下划线用于指明该属性属于”私有“,它属于一种惯例,前面加下划线只是表示你不能去访问这个这个方法和属性。以单下划线为前缀的名称应该被视为API中非公开的部分(不管是方法、函数、还是数据成员)。如果你写了代码“from <模块/包名> import *”,那么以“_”开头的名称都不会被导入,除非模块或包中的“
__all__
”列表显式地包含了它们。 -
单个下划线是一个Python命名约定,表示这个名称是供内部使用的。 它通常不由Python解释器强制执行,仅仅作为一种对程序员的提示。
-
假如在model_func.py中有函数:
def external(): return 23 def _internal(): return 25
-
现在通过通配符导入,python不会导入有单下划线的函数,除非定义了
__all__
列表from model_func import * external() _internal() 23 Traceback (most recent call last): File "mfj.py", line 3, in <module> print(_internal()) NameError: name '_internal' is not defined
名称前的双下划线
-
名称前(具体为一种方法)的双下划线,这个不是一种惯例。python中设置这种方法是为了避免子类覆盖父类的方法(为了避免与子类定义的名称冲突 )。Python文档指出,“
__spam
”这种形式(至少两个前导下划线,最多一个后续下划线)的任何标识符将会被“_classname__
spam`”这种形式原文取代,在这里“classname”是去掉前导下划线的当前类名。class A(object): def _internal_use(self): pass def __method_name(self): print('我是A的私有方法') dir(A()) a._A__method_name() ['_A__method_name', ..., '_internal_use'] 我是A的私有方法 class A(object): def __method(self): print('i am a method of A') def method_x(self): print('i am anthoder method of A') def run(self): self.__method() self.method_x() class B(A): def __method(self): print('i am a method of B') def method_x(self): self.__method() print('i am anthoder method of B') if __name__ == '__main__': a = A() a.run() print('*'*20) b = B() b.run() i am a method of A i am anthoder method of A ******************** i am a method of A i am a method of B i am anthoder method of B
-
上面的例子可以看出B类继承于A类,b实例继承run方法调用时不会覆盖A类中的
__method
方法,而普通方法会覆盖;但是假如在B类中调用__method
方法,这时候调用的就是B类自己的私有方法,同样不会被A类的私有方法覆盖,所以说对一个方法采用双下划线是为了防止继承中互相覆盖自己的私有方法。
-
-
私有属性:同样不会被子类覆盖。
class A(object): def __init__(self): self.__num = 22 def run(self): print(self.__num) class B(A): def __init__(self): self.__num = 33 if __name__ == '__main__': a = A() a.run() print('*'*20) b = B() b.run() 22 ******************** Traceback (most recent call last): File "htmldownload.py", line 63, in <module> b.run() File "htmldownload.py", line 52, in run print(self.__num) AttributeError: 'B' object has no attribute '_A__num'
名称开头结尾双下划线
-
如
__init__
,这种用法表示python中的特殊方法。其实这是一种惯例,对python系统来说,这将确保不会与用户定义的名称冲突。你也会重写这些方法,在里面实现你想要的功能,以便python调用。例如你在写类时,重写__init__
一样。 -
这种方法表示是python自己调用,你不用调用,如你用len()函数其实是python自己调用
__len__()
方法, -
操作符重载就是特殊函数的重写。
class myStr(): def __init__(self,n): self.n = n def __str__(self): return str(self.n) + 'asjbns' def __add__(self,other): return self.n + other + 10 def __sub__(self,other): return self.n - other - 10 a = myStr(5) print(a) print(a+15) print(a-5) 5asjbns 30 -10
总结
-
使用单下划线(_one_underline)开头表示方法不是API的一部分,不要直接访问(虽然语法上访问也没有什么问题)。
-
使用双下划线开头(__two_underlines)开头表示子类不能覆写该方法。除非你真的知道你在干什么,否则不要使用这种方式。
-
当你想让自己定义的对象也可以像Python内置的对象一样使用Python内置的一些函数或操作符(比如len、add、+、-、==等)时,你可以定义该类方法。
-
当然还有些属性只在末尾加了但下划线,这仅仅是为了避免我们起的一些名字和Python保留关键字冲突,没有特殊含义。