(十九)python 封装 多态 多继承 函数重写

xiaoxiao2021-03-01  14

目录

封装  enclosure

私有属性和方法:

多态  polymorphic

多继承  multiple inheritance

函数重写  overwrite

    对象转字符串的重写方法

    str(obj) 函数调用方法说明:

    内建函数重写

    数值转换函数重写

    布尔测试函数重写

迭代器(高级)


用于类的函数:    issubclass(cls,class_or_tuple)   判断一个类是否继承自其他的类,如果此类cls是class或tuple中的一个派生子类,则返回True,否则返回False

class A:     pass class B(A):     pass class C(B):     pass print(issubclass(C, B)) # True print(issubclass(B, C))  # False print(issubclass(bool, (C, B, A, int)))  # True

封装  enclosure

    封装是指隐藏类的实现细节,让使用者不用关心这些细节     封装的目的是让使用者通过尽可能少的方法(或属性)操作对象

私有属性和方法:

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

# 此示例示意用私有属性和私有方法来进行封装 class A:     def __init__(self):         self.__p1 = 100  # 创建私有属性,此属性在类外无法访问     def __m1(self):  # 私有方法         print("__m1 私有方法被调用")     def infos(self):         print("A类的infos访问的__p1属性是:", self.__p1)         self.__m1()  # 调用自己的私有方法      a = A() # print(a.__p1)  # 出错 a.infos() # a.__m1()  # 当前主模块不能调用A类的私有方法

多态  polymorphic

    什么是多态:         字面意思: 多种状态

    状态:         静态(编译时状态)         动态(运行时状态)

    多态是指在有继承/派生关系的类中,调用基类对象的方法,调用基类对象的方法,实际能调用子类的覆盖方法的现象叫多态     说明:         多态调用的方法与对象相关,不与类型相关         python全部对象都只有运行时状态(动态)         没有"c++语言"里编译时状态(静态)

# 此示例示意python的多态(动态) class Shape:     '''图形'''     def draw(self):         print("Shape的draw() 被调用") class Point(Shape):     def draw(self):         print("正在画一个点") class Circle(Point):     def draw(self):         print("正在画一个圆")          def my_draw(s):     s.draw()  # s.draw调用谁是在运行时由s的类型动态决定               # 此处显示出运行时状态 shape1 = Circle() shape2 = Point() my_draw(shape1) my_draw(shape2) L = [Point(), Circle(), Point(), Point(), Circle()] for s in L:     s.draw()

面向对象的编程语言的特征     封装     继承/派生     多态

多继承  multiple inheritance

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

    语法:         class 类名(基类名1,基类名2,...)     说明:         一个子类同时继承自多个父类,父类中的方法可以同时被继承下来         如果两个父类中有同名的方法,则在子类中又没有覆盖此方法时,         调用结果难以确定

# 此示例示意多继承的语法和用法 class Car:     def run(self, speed):         print('车正在以', speed, '公里/小时的速度行驶') class Plane:     def fly(self, height):         print('飞机以海拔', height, '米的高空飞行') class PlaneCar(Plane, Car):     '''PlaneCar类同时继承是Plane和 Car类''' p1 = PlaneCar() p1.fly(10000) p1.run(300)

多继承的问题(缺陷)     标识符(名字空间)冲突问题     要谨慎使用多继承

# 小张写了一个类: class A:     def m(self):         print("A.m() 被调用") # 小李写了一个类B class B:     def m(self):         print("B.m() 被调用") # 小王感觉小张和小李写的两个类自己可以用 class AB(A, B):     def m(self):         print("AB.m() 被调用")         super().m()         super(A, self).m() ab = AB() ab.m()  # 当AB类没有覆盖父类的方法时会出现名字冲突问题

多继承的MRO(Method Resolution Order)等问题 类的__mro__属性:     作用:         用来记录属性(或方法)的查找顺序

函数重写  overwrite

    什么是函数重写         在自定义的类内添加相应的方法,让自定义的类生成的对象(实例)         像内建对象一样进行函数操作

    对象转字符串函数:         repr(x) 返回一个能代表此对象的表达式字符串,通常:             eval(repr(obj)) = obj         str(obj) 通过给定对象,返回一个字符串(这个字符串通常是给人阅读的)  

    对象转字符串的重写方法

        repr() 函数的重写方法             def __repr__(self):                 ...                 return 字符串         str() 函数的重写方法:             def __str__(self):                 ...                 return 字符串

# 此示例示意repr函数和str函数的不同 s = "I'm Teacher" print(str(s))   print(repr(s)) class MyNumber:     def __init__(self,value):         self.data = value     def __str__(self):         print("正在调用__str__方法,转换为普通字符串")         s = "自定义数据%d" % self.data         return s        def __repr__(self):         return 'MyNumber(%d)' % self.data n1 = MyNumber(100) print(str(n1)) print(repr(n1)) # 此示例示意自定义的对象转为python内键的数字类型 class MyNumber:     def __init__(self, v):         self.data = v     def __repr__(self):         return "MyNumber(%d)" % self.data     def __int__(self):         return int(self.data) n1 = MyNumber(100.5) n = int(n1)  # 自定义类型转为整数, 出错!!! print(n)

    str(obj) 函数调用方法说明:

      1. str(obj) 函数先查找obj.__str__()方法,调用此方法并返回结果       2. 如果obj.__str__() 方法不存在,则调用obj.__repr__()方法并返回结果       3. 如果obj.__repr__方法不存在,则调用object类的__repr__实例方法显示         <__main__.MyNumber object at xxx>格式的字符串

    内建函数重写

        __abs__         abs(obj) 函数调用         __len__         len(obj) 函数调用         __reversed__   reversed(obj) 函数调用         __round__       round(obj) 函数调用

# 此示例示意 abs 和len方法的重写方法 class MyInteger:     def __init__(self, v):         self.data = v     def __repr__(self):         return 'MyInteger(%d)' % self.data     def __abs__(self):         '''此方法用于制定abs(obj) 函数取值时返回的结果'''         if self.data < 0:             # 用-self.data 创建一个新的对象返回回去             t = MyInteger(-self.data)             return t         return MyInteger(self.data) i1 = MyInteger(-100) print(i1)  # 等同于print(str(i1))  n = abs(i1) print(n)  # MyInteger(100) i2 = MyInteger(200) print(abs(i2))  # MyInteger(200)

    数值转换函数重写

        __complex__     coplex(obj)  函数调用         __int__         int(obj)  函数调用         __float__       float(obj)  函数调用         __bool__        bool(obj)  函数调用

# 此示例示意自定义的对象转为python内键的数字类型 class MyNumber:     def __init__(self, v):         self.data = v     def __repr__(self):         return "MyNumber(%d)" % self.data     def __int__(self):         return int(self.data) n1 = MyNumber(100.5) n = int(n1)  # 自定义类型转为整数, 出错!!! print(n)

    布尔测试函数重写

        格式:             def __bool__(self):                 ...         作用:         用于bool(obj)函数取值         用于if语句真值表达式中         用于while语句的值表达式中

    说明:         1.当自定义类有__bool__(self)方法时,以此方法的返回值作为bool(obj)的返回值         2. 当不存在__bool__(self)方法时,bool(x)返回__len__(self)方法的返回值是否为零来测试布尔值         3.当再不存在__len__(self)方法时,则直接返回True

# 此示例示意__bool__方法的重写方法及用法 class MyList:     def __init__(self, iterable=()):         self.data = [x for x in iterable]     def __repr__(self):         return "MyList(%s)" % self.data     def __len__(self):         print("__len__被调用")         return len(self.data)     def __bool__(self):         '''此方法用来制定一个bool(x) 返回的规则'''         # 如果没有任何元素返回False         print("__bool__方法被调用")         if len(self.data) == 0:             return False         for x in self.data:             if x:                 return True         return False myl = MyList([1, -2, 3, -4]) # myl = MyList() print(myl) print(bool(myl))  # False print(len(myl)) myl1 = MyList([0, 0.0, False, None])     print(bool(myl1))  # False myl2 = MyList([0, 1, 2]) print(bool(myl2))  # True

迭代器(高级)

    什么是迭代器        可以通过next函数取值的对象就是迭代器 

    迭代器协议         迭代器协议是指对象能够使用next函数获取下一个数据,在没有下一项数据时触发一个StopIteration异常来终止迭代的约定     迭代器的实现方法:         __next__(self) 此方法用来实现迭代器协议

    什么是可迭代对象:         是指能用iter(obj) 函数返回迭代器对象         可迭代对象内部要定义__iter__(self) 方法来返回迭代器对象

    可迭代对象的语法形式:        class MyIterable:            def __iter__(self):                语句块                return 迭代器

# 此示例示意用自定义的类MyRange实现可迭代对象 # 用自定义的类MyIterator 实现迭代器 class MyIterator:     def __init__(self, start, stop, step):         # self.start变量用来记录迭代器的起始位置和当前位置         self.start = start         self.stop = stop         self.step = step     def __next__(self):         '''此方法用于实现迭代器协议'''         print("MyIterator.__next__方法被调用!")         if self.start >= self.stop:  # 迭失终止条件             raise StopIteration         r = self.start  # 先将要返回的数存于变量r中         self.start += self.step  # 迭代器后移         return r  # 送回给next(it) 调用 class MyRange:     def __init__(self, start, stop=None, step=1):         if stop is None:             stop = start             start = 0         self.start = start  # 起始值         self.stop = stop    # 终止值         self.step = step    # 步长     def __repr__(self):         return "MyRange(%d, %d, %d)" % (self.start,             self.stop, self.step)     def __iter__(self):         '''此方法用于把MyRange类型创建的对象当做可迭代对象         '''         print("__iter__被调用")         # 此处必须返回迭代器         return MyIterator(self.start, self.stop, self.step) L = [x for x in MyRange(5, 10)] print(L) print('----------------------------') R = MyRange(5, 10, 2) it = iter(R)  # R.__iter__ print(next(it))  # it.__next__

练习:   写一个类MyList 实现和list内几乎一样的功能      在MyList类内用列表来存储数据    如:     class MyList:         def __init__(self, iterable=()):             self.data = [x for x in iterable]         def append(self, v):             ...用于添加数据         ...

class MyList: def __init__(self, iterable=()): self.data = [x for x in iterable] def append(self, v): self.data.append(v) # ...用于添加数据 def __repr__(self): return 'MyList(%r)' % self.data def __iter__(self): return MyIterator(self.data) def __len__(self): return len(self.data) # self.data.__len__() class MyIterator: def __init__(self, lst): self.data = lst # 绑定要迭代的列表  self.index = 0 # 迭代的起始位置 def __next__(self): if self.index >= len(self.data): raise StopIteration # 发送迭代结束通知 r = self.data[self.index] self.index += 1 return r # 返回此次提供的数据 L = MyList("ABCD") print(L) # MyList(['A', 'B', 'C', 'D']) L.append('E') print(L) # MyList(['A', 'B', 'C', 'D', 'E']) for x in L: print(x) # A B C D E print("列表L的长度是:", len(L)) # 5 class MyList: class MyIterator: def __init__(self, lst): self.data = lst # 绑定要迭代的列表  self.index = 0 # 迭代的起始位置 def __next__(self): if self.index >= len(self.data): raise StopIteration # 发送迭代结束通知 r = self.data[self.index] self.index += 1 return r # 返回此次提供的数据 def __init__(self, iterable=()): self.data = [x for x in iterable] def append(self, v): self.data.append(v) # ...用于添加数据 def __repr__(self): return 'MyList(%r)' % self.data def __iter__(self): return MyList.MyIterator(self.data) def __len__(self): return len(self.data) # self.data.__len__() L = MyList("ABCD") print(L) # MyList(['A', 'B', 'C', 'D']) L.append('E') print(L) # MyList(['A', 'B', 'C', 'D', 'E']) for x in L: print(x) # A B C D E print("列表L的长度是:", len(L)) # 5

 

转载请注明原文地址: https://www.6miu.com/read-3450367.html

最新回复(0)