1.属性隐藏(私有)方法:双下划线"__",是一种变形操作
- 类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式
- 特点:
- 类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果
- 这种变形其实是针对外部的变形,在外部是无法通过__x这个名字访问到的
- 在子类定义的__x不会覆盖在父类定义的__x,因为子类中变成了:_子类名__x,而父类中变形成了:_父类名__x,即双下划线开头的属性在继承给子类时,子类时无法覆盖的。
- 注意:
- 这种机制也并没有从真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__x
- 变形过程只在类定义时发生一次,在定义后的赋值操作,不会变形
1 class A: 2 __x = 1 #_A__x = 1 3 def __init__(self,name): 4 self.__name = name #self._A__name = name 5 def __foo(self): 6 print('run foo') 7 def bar(self): 8 self.__foo() # self._A__foo(),只有在类内部才可以通过__foo的形式访问到 9 print('from bar') 10 # print(A.__dict__) 11 ''' 12 {'__module__': '__main__', '_A__x': 1, 13 '__init__': <function A.__init__ at 0x0000000001E25048>, 14 '_A__foo': <function A.__foo at 0x0000000001E250D0>, 15 'bar': <function A.bar at 0x0000000001E25400>, 16 '__dict__': <attribute '__dict__' of 'A' objects>, 17 '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} 18 ''' 19 # print(A.__x) # 报错 20 # print(A.__foo)# 报错 21 # print(A._A__x) #1 22 23 a = A('egon') 24 # a._A__foo() #run foo 25 a.bar()# run foo from bar
- 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
1 #正常情况下: 2 class A: 3 def fa(self): 4 print('from A') 5 def test(self): 6 self.fa() 7 class B(A): 8 def fa(self): 9 print('from B') 10 b = B() 11 b.test()#from B,子类覆盖了父类的方法
1 #把fa定义成私有的,即__fa 2 class A: 3 def __fa(self): 4 print('from A') 5 def test(self): 6 self.__fa() 7 class B(A): 8 def __fa(self): 9 print('from B') 10 b = B() 11 b.test()#from A,隐藏后,子类不会覆盖父类的方法
2.封装
- 封装数据属性:明确的区分内外,控制外部对隐藏属性的操作行为
-
1 class Teacher: 2 def __init__(self,name,age): 3 self.__name = name 4 self.__age = age 5 def tell_info(self): 6 print('姓名:%s,年龄:%s'%(self.__name,self.__age)) 7 def edit_info(self,name,age): 8 self.__name = name 9 self.__age = age 10 t = Teacher('egon',18) 11 t.tell_info()#姓名:egon,年龄:18 12 t.edit_info('egon',28) 13 t.tell_info()#姓名:egon,年龄:28
- 封装方法:隔离复杂度
-
1 ''' 2 #取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱 3 #对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做 4 #隔离了复杂度,同时也提升了安全性 5 ''' 6 class ATM: 7 def __card(self): 8 print('插卡') 9 def __auth(self): 10 print('用户认证') 11 def __input(self): 12 print('输入取款金额') 13 def __print_bill(self): 14 print('打印账单') 15 def __take_money(self): 16 print('取款') 17 def withdrwa(self): 18 self.__card() 19 self.__auth() 20 self.__input() 21 self.__print_bill() 22 self.__take_money() 23 a = ATM() 24 a.withdrwa() 25 ''' 26 插卡 27 用户认证 28 输入取款金额 29 打印账单 30 取款 31 '''
- 扩展
- 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑
-
1 #扩展 2 class Room: 3 def __init__(self,name,owner,weight,length,height): 4 self.name = name 5 self.owner = owner 6 self.__weight = weight 7 self.__length = length 8 self.__height = height 9 def tell_area(self): 10 return self.__weight * self.__length 11 r = Room('教室','LuffyCity',10,10,3) 12 print(r.tell_area())#100