首页Python【Python基础】21....

【Python基础】21.类变量的私有化


本系列文章配套代码获取有以下三种途径:

  • 可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):

https://returu.github.io/Python_Basic/lab/index.html
链接:https://pan.baidu.com/s/1x2Ynh_VibPY2u-HWTaJo8w?pwd=mnsj 提取码:mnsj
  • 前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Basic

—————————————————

1.公有化与私有化:

之前定义的类中的属性和方法都是公有化(public),这是Python中的默认权限,方便操作的同时也会存在一定的问题,例如之前介绍的当实例变量和类变量同名,并且同时被修改时,系统会以实例变量优先,此时会导致类变量修改失败。

为了避免一些问题的出现,在定义类时,可以给予类变量一定的限制,将类变量“隐藏”起来,不允许实例化的对象直接访问类变量,这就是类变量的私有化(private)。

1.1 私有化的实现:

私有化的实现方式就是给类变量添加一个私有化权限,从而被私有化的属性不能被实例化对象直接访问,但是类中的函数可以访问。

如果实例化对象需要获取私有化属性,可以通过调用类中定义的getter函数获取。

Python规定,以两个下划线(__)开头的成员对象为私有化成员。

 1# 定义一个类
2>>class Student:
3...     
4...     # 类私有化变量,以两个下划线开头
5...     __schoolname = "光明小学"
6...     
7...     def __init__(self , name , age):
8...         self.name = name
9...         self.age = age
10...         
11...     def get_info(self):
12...         return f"学校:{self.__schoolname},姓名:{ self.name},年龄:{self.age}。"
13...     
14...     # 定义返回私有化变量的get方法
15...     def get_schoolname(self):
16...         return self.__schoolname
17
18# 实例化对象
19>>> student_1 = Student('Tom' , '12')
20# 实例化对象不能直接获取该类的私有化属性
21>>> student_1.__schoolname
22AttributeError: 'Student' object has no attribute '__schoolname'
23# 实例化对象可以通过调用类中的get函数获取该类的私有化属性
24>>> student_1.get_schoolname()
25'光明小学'

1.2 修改私有化属性:

上面通过封装的getter函数实现获取私有化变量的功能。

如果需要修改私有化属性,需要通过封装的setter函数来实现。

 1# 定义一个类
2>>class Student:
3...     
4...     # 类私有化变量,以两个下划线开头
5...     __schoolname = "光明小学"
6...     
7...     def __init__(self , name , age):
8...         self.name = name
9...         self.age = age
10...         
11...     def get_info(self):
12...         return f"学校:{self.__schoolname},姓名:{ self.name},年龄:{self.age}。"
13...     
14...     # 定义返回私有化变量的getter方法
15...     def get_schoolname(self):
16...         return self.__schoolname
17...     
18...     # 定义修改私有化变量的setter方法
19...     def set_schoolname(self , value):
20...         self.__schoolname = value
21
22# 实例化对象
23>>> student_1 = Student('Tom' , '12')
24# 通过调用类中的getter函数获取该类的私有化变量
25>>> student_1.get_schoolname()
26'光明小学'
27
28# 修改私有化变量
29>>> student_1.set_schoolname("解放小学")
30# 通过调用类中的getter函数获取该类的私有化变量
31>>> student_1.get_schoolname()
32'解放小学'

1.3 私有化的原理:

Python中通过对私有化变量名称重整(mangle)的方式来实现私有化操作的。

通过内置的__dict__属性获取该类的所有属性信息,可以看到有一个_Student__school_name变量,该变量就是私有变量可以看到Python会自动将私有变量改名,从而让实例化对象无法获取该私有变量。

 1# 获取类的类属性信息
2>>> Student.__dict__
3mappingproxy({'__module__''__main__',
4              '_Student__schoolname''光明小学',
5              '__init__': <function __main__.Student.__init__(self, name, age)>,
6              'get_info': <function __main__.Student.get_info(self)>,
7              'get_schoolname': <property at 0x29a59d95720>,
8              '__dict__': <attribute '__dict__' of 'Student' objects>,
9              '__weakref__': <attribute '__weakref__' of 'Student' objects>,
10              '__doc__': None})

下面,可以使用_Student__school_name变量名来验证,通过结果可以看出私有变量也是可以获取的,只是系统将其改了个名称而已。

下面之所以返回结果为“解放小学”,是因为在上一部分代码最后通过调用类中的setter函数修改了私有化变量。

1# 获取私有变量
2>>> student_1._Student__schoolname
3'解放小学'

2.使用装饰器方法实现类的私有化:

上面通过两个下划线(__)的命名方式实现了类的私有化属性,提高了程序的稳健性。但是必须通过预先封装的get函数才能获取私有属性信息。

为了是的私有化属性能够直接被访问,可以使用装饰器(@property)方法将getter或setter方法装饰成类中的一个属性。

2.1 装饰器实现私有变量的get函数:

使用装饰器(@property)方法将getter方法装饰成类中的一个属性。

 1# 定义一个类
2>>class Student:
3...     
4...     # 类私有化变量,以两个下划线开头
5...     __schoolname = "光明小学"
6...     
7...     def __init__(self , name , age):
8...         self.name = name
9...         self.age = age
10...         
11...     def get_info(self):
12...         return f"学校:{self.__schoolname},姓名:{ self.name},年龄:{self.age}。"
13...     
14...     # 将get函数装饰成属性
15...     @property
16...     def get_schoolname(self):
17...         return self.__schoolname
18
19
20# 实例化对象
21>>> student_1 = Student('Tom' , '12')
22# 获取私有化属性
23>>> student_1.get_schoolname
24'光明小学'

2.2 装饰器实现私有变量的set函数:

使用装饰器(@name.setter)方法将setter方法装饰成类中的一个属性。

1# 定义一个类
2>>class Student:
3...     
4...     # 类私有化变量,以两个下划线开头
5...     __schoolname = "光明小学"
6...     
7...     def __init__(self , name , age):
8...         self.name = name
9...         self.age = age
10...         
11...     def get_info(self):
12...         return f"学校:{self.__schoolname},姓名:{ self.name},年龄:{self.age}。"
13...     
14...     # 将getter函数装饰成属性
15...     @property
16...     def get_schoolname(self):
17...         return self.__schoolname
18...     
19...     # 将setter函数装饰成属性
20...     @get_schoolname.setter
21...     def set_schoolname(self , value):
22...         self.__schoolname = value
23
24
25# 实例化对象
26>>> student_1 = Student('Tom' , '12')
27# 获取私有化属性
28>>> student_1.get_schoolname
29'光明小学'
30
31# 修改私有化变量
32>>> student_1.set_schoolname = "解放小学"
33# 获取私有化属性
34>>> student_1.get_schoolname
35'解放小学'

使用“装饰器+私有变量”的方式,在提升代码稳健性的同时,也保证了对属性直接访问的取值方式,使得getter和setter方法的操作变得透明,使用起来更加方便和安全。

本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments