Python 封装

数据的封装 -- 保护隐私
方法的封装 -- 隔离复杂度

封装其实分为两个层面,但无论哪种层面的封装,都要对外界提供好访问你内部隐藏内容的接口(接口可以理解为入口,有了这个入口,使用者无需且不能够直接访问到内部隐藏的细节,只能走接口,并且我们可以在接口的实现上附加更多的处理逻辑,从而严格控制使用者的访问)

第一个层面的封装(什么都不用做):创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装

注意:对于这一层面的封装(隐藏),类名.和实例名.就是访问隐藏属性的接口

第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。

封装

在python中用双下划线的方式实现隐藏属性(设置成私有的)

封装 隐藏接口

class A:
    __x = 1   #
    def __test(self):
        print('from A')

print(A.__dict__)

结果:
{'module': 'main', '_A__x': 1, '_A__test': <function A.__test at 0x000000000231BB70>, 'dict': <attribute 'dict' of 'A' objects>, 'weakref': <attribute 'weakref' of 'A' objects>, 'doc': None}

从打印的字典中可以查看到__A被隐藏成了_A__X,前面加上的_类的名字

class A:
    __x = 1
    def __test(self):
        print('from A')

# print(A.__dict__)

# print(A._A__x)  
a = A()
A._A__test(123123)  # 直接使用类的时候用函数需要传入参数
# print(a._A__x)
# a._A__test()  # 实例化后不用传入参数self

__名字只有在类中定义的时候才会产生变形,当类和对象已经产生了,就不会有变形的效果,可以直接拿来用,相当于普通的变量

class B:   # 已经产生了类
    pass

B.__x = 1  # 在类的外面定义

print(B.__dict__)
print(B.__x)

结果:
{'module': 'main', 'dict': <attribute 'dict' of 'B' objects>, 'weakref': <attribute 'weakref' of 'B' objects>, 'doc': None, '__x': 1}

1

从字典中可以看到, '__x': 1 没有变形成_B__x

class B:   # 已经产生了类
    pass
 
b = B()  # 已经实例化了
b.__x = 1
print(b.__x)
print(b.__dict__)

结果:

1
{'__x': 1}

查找的顺序

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()  # b.txt --B --A --b.fa

结果:
from B

实例化后b.txt先从B中寻找,B中没有,从父类A中寻找,A中的test下面的执行的是self.fa(),实际的self还是传递的b,就是b.fa(),所以执行的还是B中的fa,所以运行的结果是 from B

把B中的注释

class A:
    def fa(self):
        print("from A")
    def test(self):
        self.fa()

class B(A):
    pass
b = B()
b.test()  # b.txt --B --A --

结果:
from A

实际的原理就是b.test==b.fa()

class A:
    def __fa(self):  # _A__fa
        print("from A")
    def test(self):
        self.__fa()   # self._A__test

class B(A):

    # def __fa(self):  # _B__fa
    #     print("from B ")
    pass

b = B()
b.test()  # b.txt --B --A

结果:
from A

小练习

class A:
    def __fa(self):  # _A__fa
        print("from A")
    def test(self):
        self.__fa()   # self._A__test

class B(A):

    # def __fa(self):  # _B__fa
    #     print("from B ")
    pass

b = B()
b.test()  # b.txt --B --A

原理

查找的顺序

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()  # b.txt --B --A --b.fa

结果:
from B

实例化后b.txt先从B中寻找,B中没有,从父类A中寻找,A中的test下面的执行的是self.fa(),实际的self还是传递的b,就是b.fa(),所以执行的还是B中的fa,所以运行的结果是 from B

把B中的注释

class A:
    def fa(self):
        print("from A")
    def test(self):
        self.fa()

class B(A):
    pass
b = B()
b.test()  # b.txt --B --A --

结果:
from A

实际的原理就是b.test==b.fa()

封装的接口函数

在类的内部可以用__名字访问到变形的属性

对于这一层面的封装(隐藏),我们需要在类中定义一个函数(接口函数)在它内部访问被隐藏的属性,然后外部就可以使用了

class A:
    def __init__(self):
        self.__x=1

    def tell(self):
        print(self.__x)  # 在类的内部可以直接使用__名字访问到变形的属性


a=A()
print(a.__dict__)
# print(a.__x)

a.tell()  # 可以通过调用内部的函数进行访问

模拟len(),通过调用函数的接口实现

>>> a = 'hello'
>>> l =[1,2,3,4]
>>> def func(obj):
...     return obj.__len__()
...
>>> func(a)
5
>>> func(l)
4
>>>

原文地址:https://www.cnblogs.com/Python666/p/6740510.html