【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

https://zhuanlan.zhihu.com/p/64487092

https://www.runoob.com/python/python-func-property.html

https://wiki.jikexueyuan.com/project/explore-python/Class/property.html


注:
1,在构造函数__init__中是_x,不是x,你直接x是访问不到的;
2,为什么是_x 而不是x,这是python中的私有变量(虽然python中没有公有变量和私有变量,也就是说这是伪私有),在python中,如果一个变量不想被外部直接访问,一般是在变量前加一个下划线,提醒不要直接访问(其实是可以通过self._x访问到的,如果不想被访问还可以使用双下划线__x,也是不能直接访问)所以提供get_x这样的函数供使用者访问;
3,为什么要使用_x这样的伪私有变量,因为我们使用property时,让方法变成属性的方式来调用,一般是这样写x=property(...),这样调用更加清晰明了;但是如果构造函数中的变量也用x,就会和property中的变量有冲突,所有一般我们写_x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值