面向对象——封装

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
View Code
  • 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
 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
    View Code
  • 封装方法:隔离复杂度
  •  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 '''
    View Code
  • 扩展
    • 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑
  •  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
    View Code
原文地址:https://www.cnblogs.com/GraceZ/p/8081271.html