python 类的基础概念(二)

1、封装 enclosure

  【1】封装是指隐藏类的实现细节,让使用者不关心这些细节

  【2】封装的目的是让使用者通过尽可能少的方法(或属性)操作对象

2、私有属性和方法

  【1】python类中以双下划线('__') 开头,不以双下划线结尾的标识符为私有成员,私有成员或只能用类内的方法进行访问和修改

  【2】以__开头的实例变量为私有属性

  【3】以__开头的方法为私有方法

In [175]: # 此示例示意私有属性和私有方法
     ...: class A:
     ...:     def __init__(self):
     ...:         self.__p1 = 100  # 私有属性
     ...:
     ...:     def show_A(self):
     ...:         print('self.__p1: ', self.__p1)
     ...:         self.__m1()  # 调用自己的方法
     ...:
     ...:     def __m1(self):  # 私有方法
     ...:         print("__m1(self)方法被调用")
     ...:
     ...:
     ...: a = A()
     ...: a.show_A()  # a.__p1: 100
     ...: # print(a.__p1)  # 出错,在类外部不能访问a的私有属性__p1
     ...: # a.__m1()  # 出错,不能调用私有方法
     ...:
     ...:
     ...: class B(A):
     ...:     pass
     ...:
     ...:
     ...: b = B()
     ...: # print(b.__p1)  # 出错, 子类对象不能访问父类中的私有成员
     ...: # b.__m1()  # 出错
     ...:
self.__p1:  100
__m1(self)方法被调用

3、多态 polymorphic 

  什么是多态:

    字面意思: 多种状态

    多态是指在有继承/派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态

  状态:

    静态(编译时状态)

    动态(运行时状态)

  【注】: 多态调用方法与对象相关,不与类相关

    Python的全部对象都只有"运行时状态(动态)", 没有"C++语言"里的"编译时状态(静态)"

In [176]: # 此示例示意python中的运行时状态
     ...: class Shape:
     ...:     def draw(self):
     ...:         print('Shape的draw方法被调用')
     ...:
     ...:
     ...: class Point(Shape):
     ...:     def draw(self):
     ...:         print("正在画一个点")
     ...:
     ...:
     ...: class Circle(Shape):
     ...:     def draw(self):
     ...:         print("正在画一个圆")
     ...:
     ...:
     ...: def my_draw(s):
     ...:     s.draw()  # 此处调用哪儿方法呢? 此处显示出'动态'
     ...:
     ...:
     ...: s1 = Circle()
     ...: s2 = Point()
     ...: my_draw(s2)
     ...: my_draw(s1)
正在画一个点
正在画一个圆

4、多继承 multiple inheritance

  多继承是指一个子类继承自两个或两个以上的基类。

  class 类名(基类名1, 基类名2, ...):

    pass

  【1】 一个子类同时继承自多个父类,父类中的方法可以同时被继承下来 

In [177]: # 此示例示意用多继承来派生新类
     ...: class Car:
     ...:     def run(self, speed):
     ...:         print('汽车以', speed, 'km/h的速度行驶')
     ...:
     ...:
     ...: class Plane:
     ...:     def fly(self, height):
     ...:         print("飞机以海拔", height, '米的高度飞行')
     ...:
     ...:
     ...: class PlaneCar(Car, Plane):
     ...:     '''PlaneCar类同时继承自汽车和飞机'''
     ...:
     ...:
     ...: p1 = PlaneCar()
     ...: p1.fly(10000)
     ...: p1.run(300)
飞机以海拔 10000 米的高度飞行
汽车以 300 km/h的速度行驶

  【2】 如果两个父类中有同名的方法,而在子类中又没有覆盖此方法时,调用结果难以确定

5、多继承存在的问题

  【1】标识符(名字空间)冲突的问题

In [178]: # 此示例示意多继承名字冲突问题
     ...: # 小张写了一个类A
     ...: class A:
     ...:     def m(self):
     ...:         print('A.m()被调用')
     ...:
     ...:
     ...: # 小李写了一个类B
     ...: class B:
     ...:     def m(self):
     ...:         print('B.m()被调用')
     ...:
     ...:
     ...: # 小王感觉小张和小李写的两个类自己可以用
     ...: class AB(A, B):
     ...:     pass
     ...:
     ...:
     ...: ab = AB()
     ...: ab.m()  #  请问会发生什么?
     ...:
     ...: a=AB.__mro__
     ...: print(a)
A.m()被调用
(<class '__main__.AB'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

  【2】 如果两个父类中有同名的方法,而在子类中又没有覆盖此方法时,调用结果难以确定

  要谨慎使用继承

6、多继承的 MRO (Method Resolution Order) 问题

  类的 __mro__ 属性

    此属性用来记录类的方法查找顺序

In [142]: class A:
     ...:     def go(self):
     ...:         print('A')
     ...:         # super().go()  # error
     ...:
     ...: class B(A):
     ...:     def go(self):
     ...:         print('B')
     ...:         super().go()
     ...:
     ...: class C(A):
     ...:     def go(self):
     ...:         print('C')
     ...:         super().go()
     ...:
     ...: class D(B, C):
     ...:     def go(self):
     ...:         print('D')
     ...:         super().go()
     ...:
     ...: d = D()
     ...: d.go()  #
     ...:
D
B
C
A

In [143]: print(D.__mro__)
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

 7、环境管理器

  类内有__enter__ 和 __exit__实例方法的类被称为环境管理器

  能够用with进行管理的对象必须是环境管理器

  说明:

     __enter__将在进入with语句时被调用并返回由as变量绑定的对象

    __exit__将在离开with语句时被调用,且可以用参数来判断在离开with语句时是否有异常发生并做出相应的处理  

# 此示例示意 让一个自定义的类创建的对象能够使用with语句
class A:
    '''此类的对象可用于with语句进行管'''
    def __enter__(self):
        print("已经进入with语句,资源分配成功!")
        return self  # <<<--此处返回的对象将由 as 变量绑定

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("已经离开with语句,资源释放成功!")
        if exc_type is None:
            print("当离开with语句时没有发生异常")
        else:
            print('有异常发生,异常类型是:', exc_type,
                '异常值是:', exc_val)


with A() as a:
    print("这是with中的语句")
    raise ValueError("故意制造的异常")

 

 

posted @ 2020-12-31 17:00  昱成  阅读(93)  评论(0编辑  收藏  举报