006、面向对象(三)、继承、私有属性
面向对象(三)、继承、私有属性
1、私有属性
类属性、方法 私有:
a、浅度私有: _属性 、_方法 ;可以通过 实例._属性 访问,但是设计这个私有属性的本意是别访问我 ;
b、深度私有:__属性 、__方法 ;不可以通过 实例._属性 访问,但是可以通过 f._Father__private_money 访问 ;
模块私有:
c、私有化属性、私有化方法 同样适合在 .py 模块中 ,意思是一样的 ;
不管是 浅度私有 还是 深度私有 ,设计的本意是 类 / 模块 外面 别访问该属性 ;仅限于 类 / 模块 内部访问 ;
d、类也可以做成 私有类 class _Money() 、class __PrivateMoney ,使用方法相同 ;
e、当模块 、类 要实现一个大功能,而这个大功能由很多个内部小功能组成的,这时 这些小功能可以定义为 私有的 ,不需要被外包访问 ;
示例代码如下:
# 模块 浅度私有 _hello = 'world' # 模块 浅度私有 def __hello(): print('我不想其他的模块访问') class Father(): def __init__(self, name, money, private_money): self.name = name self._money = money # 零花钱 self.__private_money = private_money # 私房钱 # 类内部可以访问私有属性 def show_money(self): print('零花钱:{0}'.format(self._money)) self.__show_private_money() # 类内部可以访问私有方法 def __show_private_money(self): print('私房钱:{0}'.format(self.__private_money)) f = Father('sky', 1000, 500) f.show_money() # 浅度私有:可以通过 实例._属性 访问,但是设计这个私有属性的本意是别访问我 ; print(f._money) # 深度私有:不可以通过 实例._属性 访问,但是可以通过 实例.类.__属性 访问 ; # print(dir(f)) print(f._Father__private_money) # print(f.__private_money) # 报错: AttributeError: 'Father' object has no attribute '__private_money'
执行结果如下:
零花钱:1000 私房钱:500 1000 500 Process finished with exit code 0
python 中 __all__ 的使用:https://www.cnblogs.com/wxlog/p/10566628.html
python模块中的__all__,用于模块导入时限制,如:from module import *
此时被导入模块若定义了__all__属性,则只有__all__内指定的属性、方法、类可被导入;若没定义,则导入模块内的所有公有属性,方法和类。
2、继承 class B(父类)
a、浅度私有: _属性 、_方法 ;可以被继承,但不建议使用 ;
b、深度私有:__属性 、__方法 ;不可以被继承 ;
c、python 可以多继承 (三姓家奴,哈哈,不会被重用。) 很少用 ;
d、子类方法 与 父类方法 同名时,重写方法 ;重写时去copy父类的函数和参数 ;
e、如果要调用父类的 同名方法, 用 super().方法() ;
f、由于python有 *args 、 *kwargs 不定长参数,参数类型随便传什么都可以,所以没有 重载 ;
g、python不支持多态,或者说 python本来就是多态语言。引入了 鸭子类型 的概念 ;
示例代码如下:
# 模块 浅度私有 def __hello(): print('我不想其他的模块访问') class Father(): def __init__(self, name, money, private_money): self.name = name self._money = money # 零花钱 self.__private_money = private_money # 私房钱 def rest(self): print('{0} 抽支烟'.format(self.name)) class Son(Father): # 重写 have_rest 方法 def rest(self): print('{0} 玩一把游戏'.format(self.name)) # 用 super().父类方法() 调用父类的属性 def have_rest(self): super().rest() s = Son('袁克定', 2000, 200) # print(s._money) # 浅度私有: _属性 、_方法 ;可以被继承,但不建议使用 ; # AttributeError: 'Son' object has no attribute '__private_money' # 深度私有:__属性 、__方法 ;不可以被继承 ; # print(s.__private_money) s.rest() s.have_rest()
执行结果如下:
D:\SkyWorkSpace\WorkSpace\Pytest\Temp\day10\venv\Scripts\python.exe D:/SkyWorkSpace/WorkSpace/Pytest/Temp/day10/test_01/test_05.py
袁克定 玩一把游戏
袁克定 抽支烟
Process finished with exit code 0
用子类对象调用父类已被覆盖的方法
class Parent: # 定义父类
def my_method(self):
print('调用父类方法')
class Child(Parent): # 定义子类
def my_method(self):
print('调用子类方法')
c = Child() # 子类实例
c.my_method() # 子类调用重写方法
super(Child, c).my_method() # 用子类对象调用父类已被覆盖的方法
执行结果如下:
D:\SkyWorkSpace\WorkSpace\Web_AutoTest\Temp\day01\venv\Scripts\python.exe D:/SkyWorkSpace/WorkSpace/Web_AutoTest/Temp/day01/ch_003/test.py
调用子类方法
调用父类方法
Process finished with exit code 0