封装是面向对象三大特性最核心的一个特性
封装就是将一段数据与功能打包并且封口,通过封装能控制接口
封装<========>整合
在类中的属性名前加__前缀,就会实现一个对外隐藏属性效果
加__前缀后可以使属性对外隐藏,但是其实本质上是
class Foo: __x = 1 # _Foo__x 在类定义阶段前检测语法时将双下划线开头的属性__x转换成_Foo__x的形式(_类名__属性名) def __f1(self): # _Foo__f1 print(‘from test‘) print(Foo.__dict__) print(Foo._Foo__x) print(Foo._Foo__f1) 导致在类外部无法直接访问双下滑线开头的属性__x,但知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如Foo._A__N, 所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。
class Foo: __x = 1 # _Foo__x = 1 这种隐藏对外不对内,因为__开头的属性会在检查类体代码语法时统一发生变形, def __f1(self): # _Foo__f1 每处都变形为一个形式 print(‘from test‘) def f2(self): print(self.__x) # print(self._Foo__x) print(self.__f1) # print(self._Foo__f1) print(Foo.__x) print(Foo.__f1) obj=Foo() obj.f2()
class Foo: __x = 1 # _Foo__x = 1 def __f1(self): # _Foo__f1 print(‘from test‘) def f2(self): print(self.__x) # print(self._Foo__x) print(self.__f1) # print(self._Foo__f1) Foo.__y=3 print(Foo.__dict__) print(Foo.__y) class Foo: __x = 1 # _Foo__x = 1 def __init__(self,name,age): self.__name=name self.__age=age obj=Foo(‘egon‘,18) print(obj.__dict__) print(obj.name,obj.age)
变形操作只会在检查类体语法的时候(定义前)发生一次,在此之后定义的__开头的属性都不会变形
定义出来还隐藏不是为了定义不了的,最后还是需要用的的。
# 设计者: class People: def __init__(self, name): self.__name = name def get_name(self): # 通过该接口就可以间接地访问到名字属性 print(self.__name) def set_name(self,val): if type(val) is not str: print(‘必须传字符串类型‘) return self.__name=val # 使用者: obj = People(‘egon‘) # print(obj.name) # 无法直接用名字属性 # obj.name = ‘EGON‘ # 无法直接更改隐藏的属性 obj.set_name("哈哈") obj.get_name() 隐藏数据属性(将数据隐藏起来)就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制
原文:https://www.cnblogs.com/Tornadoes-Destroy-Parking-Lots/p/12662632.html