【Question】
比如,有100个学生的信息,包括学生的姓名,年龄,语文分数,数学分数,你怎么用模块把这些数据组织起来呢?
数据多了,函数也多了,该怎么组织呢?你觉得还是用模块吧,用模块不是不可以,但是不方便。
【封装】
隐藏对象的属性和实现细节,仅对外提供公共访问方式。
【好处】
1. 将变化隔离,便于使用;
2. 提高复用性,安全性;
【封装原则】
1. 将不需要对外提供的内容都隐藏起来;
2. 把属性都隐藏,提供公共方法对其访问。
注:在编程语言里,对外提供的接口(接口可理解为了一个入口),就是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。
【封装2个层面】
封装其实分为两个层面,但无论哪种层面的封装,都要对外界提供好访问你内部隐藏内容的接口(接口可以理解为入口,有了这个入口,使用者无需且不能够直接访问到内部隐藏的细节,只能走接口,并且我们可以在接口的实现上附加更多的处理逻辑,从而严格控制使用者的访问)
第一个层面的封装(什么都不用做):创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装。 注意:对于这一层面的封装(隐藏),类名.和实例名.就是访问隐藏属性的接口
第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。 注意:对于这一层面的封装(隐藏),我们需要在类中定义一个函数(接口函数)在它内部访问被隐藏的属性,然后外部就可以使用了
类的封装
python通过变量名命名来区分属性和方法的访问权限,默认权限相当于c++和java中的public
类的私有属性: __private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时self.__private_attrs。
类的私有方法:__private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 self.__private_methods
虽然python不允许实例化的类访问私有数据,但可以使用 object._className__attrName 访问属性。其实python内部私有化的实现只是将attrName属性变为了_className__attrName而已
class Demo:
__id = 123456
def getId(self):
return self.__id
temp = Demo()
# print(temp.__id) # 这种写法会报错 AttributeError: 'Demo' object has no attribute '__id'
print(temp.getId()) # 123456
print(temp._Demo__id) # 123456