封装
面向对象三大特性:继承,多态,封装
如何实现属性的隐藏
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
其实这是一种变形操作
类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式。
这种变形的特点:
在类定义阶段就发生了变形
1. 在类外部无法直接使用 obj.__AttrName
2. 在类内部可以直接使用 obj.__AttrName
3. 子类无法覆盖父类__开头的属性(在类的定义阶段就发生了变形,子类和父类的看起来的同名函数就已经发生了变形:_子类名__函数名/_父类名__函数名)
例1
class A:
__x = 1 # _A__x = 1
def __init__(self,name):
self.__name = name # self._A__name = 'wyq'
def __foo(self): # _A__foo
print('run foo')
def bar(self):
self.__foo()
print('from bar')
print(A.__dict__)
a = A('wyq')
a.bar()
例2
class Foo:
def __func(self): # _Foo__func
print('from foo')
class Bar(Foo):
def __func(self): # _Bar__func
print('from bar')
b = Bar()
总结这种变形需要注意的问题:
1.这种机制也并没有真正意义上的限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了。
2.变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形
3.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
class B:
__x = 1
def __init__(self, name):
self.__name = name
# 验证问题一
print(B._B__x)
# 验证问题二
B.__y = 2
print(B.__dict__) # {....... ,'__y': 2}
b = B('wyq')
print(b.__dict__)
# 验证问题三
class A:
def __foo(self):
print('A.foo')
def bar(self):
print('A.bar')
self.__foo()
class B(A):
def __foo(self):
print('B.foo')
b = B()
b.bar()