我的Python学习笔记(三):私有变量
一、私有变量的定义
在Python中,有以下几种方式来定义变量:
- xx:公有变量
- _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入
- __xx:双前置下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到)
- __xx__:双前后下划线,系统定义名字(不要自己发明这样的名字)
- xx_:单后置下划线,用于避免与Python关键词的冲突
如以下例子所示,我在test类中定义了num,_num 和 __num三个属性,并创建了test的类对象t,对这三个属性进行访问,__num不能被访问到
class test(object): def __init__(self): self.num = 10 self._num = 20 self.__num = 30 t = test() print(t.num) # 10 print(t._num) # 20 # print(t.__num) # AttributeError: 'test' object has no attribute '__num'
可以使用命令dir查看t中的属性和方法,__num的名字已经被重整为“_test__num”了,可以使用t._test__num对__num进行访问
注:虽然私有变量可以通过_类名__变量名来访问,但强烈建议不要这样做
二、使用不同方法导入模块,模块中私有变量的使用区别
在使用不同方法导入模块后,是否能使用模块中的私有属性和方法,有以下两种情况
- 在使用 from somemodule import * 导入模块的情况下,不能导入或使用私有属性和方法
- 在使用 import somemodule 导入模块的情况下,能导入并使用私有属性和方法
首先我们先创建一个test.py文件,将下面代码复制进去:
num = 10 _num = 20 __num = 30 def test(): print("--test--") def _test2(): print("--test2--") def __test3(): print("---test3--")
- 使用 from somemodule import * 进行导入,不能导入私有变量,结果如下:
In [1]: from test import * In [2]: num Out[2]: 10 In [3]: _num --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-3-6dd7111d6a95> in <module>() ----> 1 _num NameError: name '_num' is not defined In [4]: __num --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-4-f0ba2c4a214a> in <module>() ----> 1 __num NameError: name '__num' is not defined In [5]: test() --test-- In [6]: _test2() --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-6-d29889233d08> in <module>() ----> 1 _test2() NameError: name '_test2' is not defined In [7]: __test3() --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-7-17e592a156f3> in <module>() ----> 1 __test3() NameError: name '__test3' is not defined
- 使用 import somemodule 进行导入,能导入私有变量,结果如下:
In [8]: import test In [9]: test.num Out[9]: 10 In [10]: test._num Out[10]: 20 In [11]: test.__num Out[11]: 30 In [12]: test.test() --test-- In [13]: test._test2() --test2-- In [14]: test.__test3() ---test3--
三、对类中的私有属性进行操作的方法
如果你想对类中的私有属性进行操作时,有以下三种方法:
1、getter和setter:
添加getter和setter方法,类对象通过调用这两种方法来对私有属性进行操作
class test(object): def __init__(self): self.__num = 10 def getNum(self): return self.__num def setNum(self, value): self.__num = value t = test() print(t.getNum()) # 10 t.setNum(20) print(t.getNum()) # 20
2、property方法
class test(object): def __init__(self): self.__num = 10 def getNum(self): return self.__num def setNum(self, value): self.__num = value num = property(getNum,setNum) t = test() print(t.num) # 10 t.num = 20 print(t.num) # 20
关于property方法,我们来看下官方文档:
由文档可得:
- property方法包含四个参数,分别为fget,fset,fdel,doc,分别对应getter方法,setter方法,deleter方法和方法说明
- property()方法返回一个property属性,如果c是C的实例,那么c.x会调用getter方法,c.x = value会调用setter方法,而del c.x会调用deleter方法
3、@property
class test(object): def __init__(self): self.__num = 10 @property def num(self): return self.__num @num.setter def num(self, value): self.__num = value t = test() print(t.num) # 10 t.num = 20 print(t.num) # 20
关于@property,官方文档如下:
根据文档可得:
- 我们可以把property()方法当成一个装饰器来使用,使用@property对方法进行装饰
- 装饰器@property把方法x()转换成了与方法名同名的getter方法,"I'm the 'x' property."是property的doc参数
- 调用方法和property()方法一样