本系列文章配套代码获取有以下三种途径:
-
可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):
https://returu.github.io/Python_Basic/lab/index.html
-
也可以通过百度网盘获取,需要在本地配置代码运行环境,环境配置可以查看【Python基础】2.搭建Python开发环境:
链接: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方法的操作变得透明,使用起来更加方便和安全。
本篇文章来源于微信公众号: 码农设计师