封装
将具体、复杂的细节封装在一起。
1. 如何将属性隐藏
如果想让属性或方法隐藏,在其前加 ‘__’ 双下划线,python就将其视为私有。
注意:
(1). 私有变量是在定义时生成的。
(2). python没有实现绝对的私有,而是在定义时将私有属性解析 ‘_类名__属性’,(单下划线类名双下划线属性)
#其实这仅仅这是一种变形操作 #类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式: class A: __x = 1 #定义时被解释为 _A__x def __init__(self, name): self.__name = name # 定义时被解释为 self._A__name def __foo(self): #定义时被解释为 _A__foo print('run foo') def bar(self): self.__foo() #只有在类内部才可以通过__foo的形式访问到. # 外部无法通过‘类名.属性’的方式访问 # print(A.__x) AttributeError: type object 'A' has no attribute '__x' a = A('yk') print(a.__dict__) # {'_A__name': 'yk'} print(_A__name) # yk 可以通过_类名__x的形式访问
特点:
1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。
2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。
3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
问题:
1、这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N。
2、变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形
3、在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
#正常情况 class A: def fa(self): print('from A') def test(self): self.fa() class B(A): def fa(self): print('from B') b=B() b.test() # from B #把fa定义成私有的,即__fa class A: def __fa(self): #在定义时就变形为_A__fa print('from A') def test(self): self.__fa() #只会与自己所在的类为准,即调用self._A__fa class B(A): def __fa(self): print('from B') b=B() b.test() # from A
2. 封装不是单纯意义的隐藏
# 1:封装数据。将数据隐藏起来这不是目的。 # 隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加上对该数据操作的限制, # 以此完成对数据属性操作的严格控制。 class People: def __init__(self,name,age): self.__name = name self.__age = age # 访问接口 def tell_info(self): print('姓名:%s,年龄:%s' % (self.__name, self.__age)) # 修改接口 def set_info(self, name, age): # 添加自己的控制逻辑 if not isinstance(name, str): raise TypeError('姓名必须是字符串类型') if not isinstance(age, int): raise TypeError('年龄必须是整型') self.__name = name self.__age = age p = People('yk',18) p.tell_info() # yk,年龄:18 p.set_info('小明',15) p.tell_info() # 小明,年龄:15 p.set_info('小花','14') # 报错 TypeError: 年龄必须是整型
# 2:封装方法,隔离复杂度 #取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱 #对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做 #隔离了复杂度,同时也提升了安全性. class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() a=ATM() a.withdraw()