Python
用下划线作为前缀和后缀指定特殊变量和定义方法,主要有如下四种形式:
l
单下划线(
_
)
l
名称前的单下划线(如:
_name
)
l
名称前的双下划线(如:
__name
)
l
名称前后的双下划线(如
:__init__
)
(一)
单下划线(
_
)
只有单
下
划线的情况,主要有两种使用场景:
1
、在交互式解释器中,单下划线“
_
”代表的是上一条执行语句的结果。如果单下划线前面没有语句执行,
那么
交互式解释器将会报单下划线没有定义的错误。也可以对单下划线进行赋值操作,这时单下划线代表赋值的结果。但是一般不建议对单下划线进行赋值操作,因为单下划线内建标识符。
>>> _
Traceback (most recent call last):
File "", line 1, in
_
NameError: name '_' is not defined
>>> "python"
'python'
>>> _
'python'
>>> _="Java"
>>> _
'Java'
>>>
2
、单下划线“
_
”还可以作为特殊的临时变量。如果一个变量在后面不会再用到,并且不想给这个变量定义名称,
那么
这时就可以用单下划线作为临时性的变量。
例如,
对
for
循环语句遍历的结果元素并不感兴趣,此时就可以用单下划线表示。
# _
这个变量在后面不会用到
for _ in range(5):
print("Python")
(二)
名称前的单下划线(如:
_name
)
当在属性和方法前面加上单下划线
“
_
”,用于指定属性和方法是“私有”的。但是
Python
不像
Java
一样具有私有属性、方法、类,在属性和方法之前加单下划线,只是代表该属性、方法、类只能在内部使用,是
API
中非公开的部分。如果用
from import *
和
from import *
时,这些属性、方法、类将不被导入。
# Test.py
文件
#
普通属性
value="Java"
#
单下划线属性
_otherValue="Python"
#
普通方法
def method():
print("
我是普通方法
")
#
单下划线方法
def _otherMethod():
print("
我是单下划线方法
")
#
普通类
class PClass(object):
def __init__(self):
print("
普通类的初始化
")
#
单下划线类
class _WClass(object):
def __init__(self):
print("
单下划线类的初始化
")
将上述的
Test.py
文件导入,进行测试。
>>> from Test import *
>>> value
'Java'
>>> _otherValue
Traceback (most recent call last):
File "", line 1, in
_otherValue
NameError: name '_otherValue' is not defined
>>> method()
我是普通方法
>>> _otherMethod()
Traceback (most recent call last):
File "", line 1, in
_otherMethod()
NameError: name '_otherMethod' is not defined
>>> p=PClass()
普通类的初始化
>>> w=_WClass()
Traceback (most recent call last):
File "", line 1, in
w=_WClass()
NameError: name '_WClass' is not defined
从上面的结果可以看出,不管是属性、方法和类,只要
在
名称前面加了单下划线,都不能导出。如果对程序
Test.py
进行修改,在
文件
开头加入
__all__
,
结果会是如何?
#
将普通属性、单下划线的属性、方法、和类加入
__all__
列表
__all__=["value"
,
"_otherValue","_otherMethod","_WClass"]
修改后继续测试:
>>> from Test import *
>>> value
'Java'
>>> _otherValue
'Python'
>>> method()
Traceback (most recent call last):
File "", line 1, in
method()
NameError: name 'method' is not defined
>>> _otherMethod()
我是单下划线方法
>>> p=PClass()
Traceback (most recent call last):
File "", line 1, in
p=PClass()
NameError: name 'PClass' is not defined
>>> w= _WClass()
单下划线类的初始化
__all__
是一个字符串列表,不管是普通的还是单下划线的属性、方法和类,都将导出来,使用其他不在这个字符列表上的属性、方法和类,都会报未定义的错误。不管是属性、方法和类,只要名称前面加了单下划线,都不能导入。除非是模块或包中的“
__all__
”列表显式地包含了它们。
(三)
名称前的双下划线(如:
__name
)
先看看下面的程序:
class Method(object):
#
构造器方法
def __init__(self, name):
#
双下划线属性
self.__name = name
#
普通方法
def sayhello(self):
print("Method say hello!")
#
双下划线方法
def __sayhi(self):
print("Method say hi!")
#
初始化
Method
m = Method("Python")
#
调用
sayhello
方法
m.sayhello()
#
调用
sayhi
方法
m.__sayhi()
#
输出属性
__name
print(m.__name)
上面的程序定义了一个类,这个类有三个方法,一个构造器方法,一个普通方法,一个双下划线方法,以及包括一个双下划线的属性。上面
的
输出结果
是
:
Method say hello!
Traceback (most recent call last):
File "", line 18, in
AttributeError: 'Method' object has no attribute '__sayhi'
实际上,当对象调用
__sayhi()
方法时,将会报
Method
类没有这个方法属性的错误。那如何去调用以双下划线开头的方法和属性?
Python
这样设计的目的是什么?
首先回答第一个问题,读者看完下面的程序就知道怎么调用了。
class Method(object):
def __init__(self, name):
self.__name = name
def sayhello(self):
print("Method say hello!")
def __sayhi(self):
print("Method say hi!")
#
初始化
Method
m = Method("Python")
#
调用
sayhello
方法
m.sayhello()
#
调用
sayhi
方法
#m.__sayhi()
m._Method__sayhi()
#
输出属性
__name
#print(m.__name)
print(m._Method__name)
输出结果如下:
Method say hello!
Method say hi!
Python
从上面的程序中可以很清楚的看到,如果要调用以双下划线开头的方法和属性,只要以
“
_
类名
__
方法(属性)”的形式就可以实现方法或者属性的访问了。类前面是单下划线,类名后面是双下划线,然后再加上方法或者属性。但是并不建议调用,因为这是
Python
内部进行调用的形式。
回答完第一个问题,我们看看第二个问题,
Python
这样设计的目的是什么?
有很多人认为,
Python
以双下划线开头的方法和属性表示私有的方法和属性,实际上这样的理解不太准确,也不能说完全错误的。但是这并不是
Python
设计的目的和初衷,我们先看看下面一段程序和程序运行结果
:
class AMethod(object):
def __method(self):
print("__method in class Amethod!")
def method(self):
self.__method()
print("anthod method in class AMethod!")
class BMethod(AMethod):
def __method(self):
print("__method in class Bmethod!")
if __name__=="__main__":
print("
调用
AMethod
的
method
方法
")
a = AMethod()
a.method()
print("
调用
BMethod
的
method
方法
")
b = BMethod()
b.method()
上面的程序定义了两个类,一个是
AMethod
类,另外一个是继承了
AMethod
类的
BMethod
类。在
AMethod
类中,定义了两个方法,一个是以双下划线开头的
__method
方法,另外一个是普通方法。在
BMethod
类中,重写了
AMethod
类中的
__method
方法。
程序运行结果:
调用
AMethod
的
method
方法
__method in class Amethod!
anthod method in class AMethod!
调用
BMethod
的
method
方法
__method in class Amethod!
anthod method in class AMethod!
运行结果并不是我们想要的结果,
b.method()
并没有调用
BMethod
类的
__method
方法,而这个设计的实际目的是为了避免父类的方法被子类轻易的覆盖。
(四)
名称前后的双下划线(如
:
__init__
)
在
Python
类中,可以常常看到类似于“
__init__
”的方法,这表示在
Python
内部调用的方法,一般不建议在程序中调用。比如,当调用
len()
方法时,实际上调用了
Python
中内部的
__len__
方法,虽然不建议调用这种以双下划线开头以及结尾的方法,但是可以对这些方法进行重写。比如下面的例子:
class Number(object):
def __init__(self, number):
self.number = number
def __add__(self, number):
#
重写方法,返回两个数的差值
return self.number - number
def __sub__(self, number):
#
重写方法,返回两个数的和
return self.number + number
def __str__(self):
#
重写方法,返回字符串
return str(self.number)
num = Number(100)
print(num) # 100
调用了
__str__
方法
print(num+50) # 50 +
调用了
__add__
方法
print(num-20) # 120 -
调用了
__sub__
方法
相信看了上面所有对
Python
中下划线作用的讲解,完全能够理解上述四种下划线所表示的意义。最后将对上面的,进行总结。
(五)
总结
l
单下划线(
_
)
:
在交互解释器中,表示上一条语句执行输出的结果。另外,单下划线还可以作为特殊的临时变量,表示在后面将不会在用到这个变量。
l
名称前的单下划线:只能在内部使用,是
API
中非公开的部分,不能被
import
*
和
from
import
*
导入程序中,除非在
__all__
列表中包含了以单下划线开头的属性、方法以及类。
l
名称前的双下划线:以双下划线开头的属性、方法表示避免父类的属性和方法被子类轻易的覆盖,一般不建议这样定义属性和方法,除非你自己将要做什么。
l
名称前后的双下划线:这类方法是
Python
内部定义的方法,可以重写这些方法,这样
Python
就可以调用这个重写的方法以及利用操作符。
About Me
........................................................................................................................
● 本文作者:小麦苗,部分内容整理自网络,若有侵权请联系小麦苗删除
........................................................................................................................
● QQ群号:
230161599
(满)
、618766405
● weixin群:可加我weixin,我拉大家进群,非诚勿扰
● 联系我请加QQ好友
(
646634621
)
,注明添加缘由
● 于 -01-01 06:00 ~ -01-31 24:00 在魔都完成
● 最新修改时间:-01-01 06:00 ~ -01-31 24:00
● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
........................................................................................................................
........................................................................................................................
使用
weixin客户端
扫描下面的二维码来关注小麦苗的weixin公众号(
xiaomaimiaolhr
)及QQ群(DBA宝典)、添加小麦苗weixin,
学习最实用的数据库技术。
........................................................................................................................