【Python笔记】单下划线和双下划线
⼀、变量的定义
在 在Python 中,有以下⼏种⽅式来定义变量:
xx:公有变量
_xx:前置单下划线,私有化属性或⽅法,⼀般来讲,变量名_xx被看作是“私有 的”,在模块(看导⼊⽅法)或类外不可以使⽤。当变
量是私有的时候,⽤_xx 来表⽰变量是很好的习惯。类对象(及类的实例对象)和⼦类可以访问,这并不能完全做到真正的私有,只是约
定俗成的⽽已,这样写表⽰不希望这个变量在外部被直接调⽤
_xx:前置双下划线,私有化属性或⽅法,⽆法在外部直接访问(名字重整所以访问不到,只能是允许这个类本⾝进⾏访问了。连⼦类
也不可以)
xx:前后双下划线,系统定义名字(这就是在python中强⼤的魔法⽅法),因为变量名__xxx__对Python 来说有特殊含义,对于
普通的变量应当避免这种命名风格。
xx:后置单下划线,⽤于避免与Python关键词的冲突
如以下例⼦所⽰,我在test类中定义了x,_x和 __x三个属性,并创建了test的类对象t,对这三个属性进⾏访问,__x不能被访问到
>>> class test(object):
... def __init__(self):
... self.x = 10
... self._x = 20
... self.__x = 30
... def call_for(self):
... print('x : ', self.x)
... print('_x: ', self._x)
... print('__x: ', self.__x)
... def _call_for(self):
... print('x : ', self.x)
... print('_x: ', self._x)
... print('__x: ', self.__x)
...
>>> t = test()
>>> t.x
10
>>> t._x
20
>>> t.__x #因为译名所以不可以调⽤
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'test' object has no attribute '__x'
>>> t.call_for()
x : 10
_x: 20
__x: 30
>>> t._call_for()#也可以调⽤
x : 10
_x: 20
__x: 30
可以使⽤命令dir查看t中的属性和⽅法,__x的名字已经被重整为“_test__x”了,如果你⾮要通过外部访问,也是可以的,可以使⽤
t._test__x对__x进⾏访问。
python中没有真正的公有和私有变量,python只是对变量名称做了⼀个变化,还是可以在外部访问到的,是伪私有。
注:虽然私有变量可以通过_类名__变量名来访问,但强烈建议不要这样做!
⼆、使⽤不同⽅法导⼊模块,模块中私有变量的使⽤区别
在使⽤不同⽅法导⼊模块后,是否能使⽤模块中的私有属性和⽅法,有以下两种情况
使⽤ from somemodule import * 进⾏导⼊,不能导⼊私有变量和⽅法
在使⽤ import somemodule 导⼊模块的情况下,能导⼊并使⽤私有属性和⽅法
test.py⽂件如下:
y = 5
_y = 10
__y = 15
def call_for():
print('y : ', y)
print('_y: ', _y)
print('__y: ', __y)
def _call_for():
print('y : ', y)
print('_y: ', _y)
print('__y: ', __y)
def __call_for():
print('y : ', y)
print('_y: ', _y)
print('__y: ', __y)
运⾏:
#⼀import test
>>> import test
>>> test.y
5
>>> test._y
10
>>> test.__y
15
>>> test.call_for()
y : 5
_y: 10
__y: 15
>>> test._call_for()
y : 5
_y: 10
__y: 15
>>> test.__call_for()
y : 5
_y: 10
__y: 15
#⼆ from test import *
>>> from test import *
>>> y
5
>>> _y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_y' is not defined
>>> __y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '__y' is not defined
>>> call_for()
y : 5
_y: 10
__y: 15
>>> _call_for()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '_call_for' is not defined
>>> __call_for()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '__call_for' is not defined
三、对类中的私有属性进⾏操作的⽅法
如果你想对类中的私有属性进⾏操作时,有以下两种⽅法种⽅法:
1,⾃定义⼀个⽅法
class test(object):
def __init__(self):
self.__x = 10
def get_x(self):
return self.__x
def set_x(self, value):
self.__x = value
t = test()
print(t.get_x()) # 10
t.set_x(30)
print(t.get_x()) # 30
2,就是使⽤property
class C(object):
def __init__(self):
self._x = 0
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
class test(object):
def __init__(self):
self._x = 10
@property
def get_x(self):
return self._x
@get_x.setter
def set_x(self, value):
self._x = value
class Score(object):
def __init__(self):
self._x = 10
@property
def score(self):
return self._x
@score.setter
def score(self, value):
self._x = value
t = test()
print(t.get_x) # 10
t.set_x=30 #等价于调⽤t.sert_x(30)
print(t.get_x) # 3
s=Score()
print(s.score)#10
s.score=30
print(s.score)#30
c=C()
print(c.x)#0
c.x=10
print(c.x)#10
注:
1,在构造函数__init__中是_x,不是x,你直接x是访问不到的;
2,为什么是_x ⽽不是x,这是python中的私有变量(虽然python中没有公有变量和私有变量,也就是说这是伪私有),在python中,如
果⼀个变量不想被外部直接访问,⼀般是在变量前加⼀个下划线,提醒不要直接访问(其实是可以通过self._x访问到的,如果不想被访问还
可以使⽤双下划线__x,也是不能直接访问)所以提供get_x这样的函数供使⽤者访问;
3,为什么要使⽤_x这样的伪私有变量,因为我们使⽤property时,让⽅法变成属性的⽅式来调⽤,⼀般是这样写x=property(…),这样调
⽤更加清晰明了;但是如果构造函数中的变量也⽤x,就会和property中的变量有冲突,所有⼀般我们写_x