一、引子
从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小猫,小狗,小王八等一起装进麻袋,然后把麻袋封上口子。
照这种逻辑看,封装=‘隐藏’,这种理解是相当片面的
二、如何实现属性的隐藏
1、在python中用双下划线开头的方式将属性隐藏起来,示例代码如下:
1 class A: 2 __x = 1 3 4 def __init__(self, name): 5 self.name = name 6 7 def __foo(self): 8 print('run foo') 9 10 print(A.__x) 11 12 结果为: 13 14 Traceback (most recent call last): 15 File "C:/Users/xudachen/PycharmProjects/Python全栈开发/第三模块/面向对象/17 封装之如何实现属性的隐藏.py", line 12, in <module> 16 print(A.__x) 17 AttributeError: type object 'A' has no attribute '__x'
不仅类A无法访问,A的实例化对象也无法访问
1 a = A('tel') 2 print(a.__x) 3 4 结果为: 5 6 Traceback (most recent call last): 7 File "C:/Users/xudachen/PycharmProjects/Python全栈开发/第三模块/面向对象/17 封装之如何实现属性的隐藏.py", line 16, in <module> 8 print(a.__x) 9 AttributeError: 'A' object has no attribute '__x'
查看A的名称空间:
print(A.__dict__) 结果为: {'__module__': '__main__', '_A__x': 1, '__init__': <function A.__init__ at 0x000001B835A03510>, '_A__foo': <function A.__foo at 0x000001B837A9C620>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
查看对象a的名称空间
print(a.__dict__) 结果为: {'_A__name': 'tel'}
可以看出,当在属性名前添加__后,发生了变形,这种变形规则是_类名__属性名,
这种变形的特点是:
1、在类外部无法直接obj.__AttrName
2、在类内部是可以直接使用:obj.__AttrName的
示例代码如下:
1 class A: 2 __x = 1 3 4 def __init__(self, name): 5 self.__name = name 6 7 def __foo(self): 8 print('run foo') 9 10 def bar(self): 11 self.__foo() 12 print('from bar') 13 14 a = A('tel') 15 a.bar() 16 17 结果为: 18 19 run foo 20 from bar
这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
3、子类无法覆盖父类__开头的属性
实例代码如下:
1 class Foo: 2 def __func(self): # _Foo__func 3 print('from foo') 4 5 6 class Bar(Foo): 7 def __func(self): # _Bar__func 8 print('from bar')
表面上看函数名一样,但是定义阶段就发生了变化,所以子类与父类的函数是不一样的,所以说无法覆盖
三、隐藏属性的变形是发生在类定义阶段,类定义代码之外是不会发生变形的,实例代码如下:
1 class B: 2 __x = 1 3 4 def __init__(self, name): 5 self.__name = name 6 7 # print(B._B__x) 8 9 B.__y = 2 10 print(B.__dict__) 11 12 结果为: 13 14 {'__module__': '__main__', '_B__x': 1, '__init__': <function B.__init__ at 0x00000212E0CF3510>, '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__doc__': None, '__y': 2}
__x 在类定义内部,所以发生了变形,__y 在类定义外部,所以并未发生变形
对于对象来说也是如此,例如:
1 b = B('alex') 2 print(b.__dict__) 3 b.__age = 18 4 print(b.__dict__) 5 6 结果为: 7 8 {'_B__name': 'alex'} 9 {'_B__name': 'alex', '__age': 18}
四、为类内部的函数属性加上__,可以强制执行类内部的函数
例如:
1 class A: 2 def __foo(self): # _A__foo 3 print('A.foo') 4 5 def bar(self): 6 print('A.bar') 7 self.__foo() # self._A__foo() 8 9 class B(A): 10 def __foo(self): # _b__foo 11 print('B.foo') 12 13 b = B() 14 b.bar() 15 16 结果为 17 18 A.bar 19 A.foo