python基础教程:多态、多继承、函数重写、迭代器详细教程
用于类的函数 issubclass(cls,class_or_tuple)
判断一个类是否继承自其他的类,如果此类cls是class或tuole中的一个派生(子类)则返回True,否则返回False
封装 enclosure
封装的目的是让使用者尽可能少的引用实例变量(属性)进行操作
私有属性:python类中,以双下划线‘__’开头,不以双下划线结尾的标识符为私有成员,在类的外部无法直接访问。
class A:def __init__(self):self.__p1 = 100 #__p1为私有属性,在类的外部不可访问def test(self):print(self.__p1) # 可以访问self.__m1() # A类的方法可以调用A类的私有方法def __m1(self):'''我是私有方法,只有我自己的类中的方法才能调用我哦'''print("我是A类的__m1方法!")a = A() # 创建对象# print(a.__p1) # 在类外看不到__p1属性,访问失败!a.test()# a.__m1() # 出错.无法调用私有方法多态 polymorphic
多态是指在继承\派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖版本方法的现象叫多态
''' 学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025 寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' 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() # 此处显示出多态中的动态s1 = Circle() s2 = Point() my_draw(s1) # 调用Circle里的draw 正在画一个圆 my_draw(s2) # 调用Point里的draw 正在画一个点多继承 multiple inheritance
多继承是指一个子类继承自两个或两个以上的基类
说明:一个子类可以同时继承自多个父类,父类中的方法可以同时被继承下来。如果两个父类中有同名的方法,而在子类中又没有覆盖此方法时,调用结果难以确定
class Car:def run(self, speed):print("汽车以", speed, '公里/小时的速度行驶')class Plane:def fly(self, height):print("飞机以海拔", height, '的高度飞行')class PlaneCar(Car, Plane):'''PlaneCar同时继承自汽车类和飞机类'''p1 = PlaneCar() p1.fly(10000) p1.run(300)多继承的问题(缺陷):名字冲突问题,要谨慎使用多继承(会先使用第一个继承的基类)
命名冲突
class A:def m(self):print("A.m()被调用")class B:def m(self):print('B.m()被调用')class AB(A, B):passab = AB() ab.m() # A.m()被调用继承的MRO(Method Resolution Order)问题
类的__mro__属性用来记录继承方法的查找顺序
多继承顺序
''' 学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025 寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' class A:def m(self):print("A.m") class B(A):def m(self):print("B.m") class C(A):def m(self):print("C.m") class D(B, C):'''d类继承自B,C'''def m(self):print("D.m") d = D() print(D.__mro__) #(<class '__main__.D'>, # <class '__main__.B'>, # <class '__main__.C'>, # <class '__main__.A'>, # <class 'object'>) d.m() # 调用方法的顺序如上所示多继承顺序2
class A:def m(self):print("A.m") class B(A):def m(self):print("B.m")super().m() class C(A):def m(self):print("C.m")super().m() class D(B, C):'''d类继承自B,C'''def m(self):print("D.m")super().m() d = D() d.m() # 调用方法的顺序是什么?for x in D.__mro__:print(x)# D.m # B.m # C.m # A.m # <class '__main__.D'> # <class '__main__.B'> # <class '__main__.C'> # <class '__main__.A'> # <class 'object'>函数重写
在自定义类内添加相应的方法,让自定义类创建的实例能像内建对象一样进行内建函数操作
对象转字符串函数:
repr(obj) 返回一个能代表此对象的表达式字符串,通常eval(repr(obj))==obj (这个字符串通常是给python解释执行器运行用的)
对象转字符串函数的重写方法
reper(obj)函数的重写方法:
def__repr__(self):return 能够表达self内容的字符串str(obj)函数的重写方法:
def__str__(self):return 人能看懂的字符串重写方法
class MyNumber:def __init__(self, value):self.data = valuedef __str__(self):print("__str__被调用")return "数字: %d" % self.datadef __repr__(self):print("__repr__被调用")return 'MyNumber(%d)' % self.data n1 = MyNumber(100) # print(str(n1)) # 调用 n1.__str__(self);__str__被调用;数字: 100 # print(repr(n1)) #__repr__被调用 MyNumber(100) print(n1) # ;__str__被调用;数字: 100 # n2 = eval("MyNumber(100)") # print(n2) #__str__被调用;数字: 100说明:
1、str(obj)函数先调用obj.__str__()方法,调用此方法并返回字符串
2、如果obj没有__str__()方法,则调用obj.__repr__()方法返回的字符串
3、如果obj没有__repr__()方法,则调用object类的__repe__()实例方法显示<xxxx>格式的字符串
数值转换函数的重写
def __complex__(self) complex(obj) 函数调用 def __int__(self) int(obj) 函数调用 def __float__(self) float(obj) 函数调用 def __bool__(self) bool(obj) 函数调用自定义类可以转成数值类型
'''此示例示意自定义的类MyNumber能够转成为数值类型''' class MyNumber:def __init__(self, v):self.data = vdef __repr__(self):return "MyNumber(%d)" % self.datadef __int__(self):'''此方法用于int(obj) 函数重载,必须返回整数此方法通常用于制订自义定对象如何转为整数的规则'''return 10000n1 = MyNumber(100) print(type(n1)) # if n1 == 100: # print("n1 == 100") n = int(n1) print(type(n)) print(n)输出:
<class '__main__.MyNumber'> <class 'int'> 10000内建函数的重写
__abs__ abs(obj) __len__ len(obj) __reversed__ reversed(obj) __round__ round(obj) # 自定义一个MyList类,与系统内建的类一样, # 用来保存有先后顺序关系的数据 ''' 学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025 寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' class MyList:'''自定义列表类'''def __init__(self, iterator=[]):self.data = [x for x in iterator]def __repr__(self):return "MyList(%r)" % self.datadef __abs__(self):# return MyList([abs(x) for x in self.data])# 上一句语句可以用如下生成表达式代替已防止过多占内存return MyList((abs(x) for x in self.data))def __len__(self):# return self.data.__len__()return len(self.data)myl = MyList([1, -2, 3, -4]) print(myl) print(abs(myl)) # MyList([1, +2, 3, +4]) print("原来的列表是:", myl)myl2 = MyList(range(10)) print(myl2) print('myl2的长度是:', len(myl2)) print('myl的长度是: ', len(myl))输出:
MyList([1, -2, 3, -4]) MyList([1, 2, 3, 4]) 原来的列表是: MyList([1, -2, 3, -4]) MyList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) myl2的长度是: 10 myl的长度是: 4布尔测试函数的重写
格式 def bool(self):
…
作用:
用于bool(obj) 函数取值
用于if语句真值表达式中
用于while语句真值表达式中
说明:
输出:
__bool__方法被调用!False__bool__方法被调用!myl 是假值迭代器(高级)
可以通过next(it) 函数取值的对象就是迭代器
迭代器协议:迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIterator来终止迭代的约定
实现方法:类内需要有 __next__(self)方法来实现迭代器协议
语法形式:
可迭代对象是指能用iter(obj) 函数返回迭代器的对象(实例),可迭代对象内部一定要定义__iter__(self)方法来返回迭代器
可迭代对象的语法形式:
class MyIterable:def __iter__(self):语句块return 迭代器 # 此示例示意可迭代对象和迭代器的定义及使用方式: class MyList:def __init__(self, iterator):'''自定义列表类的初始化方法,此方法创建一个data实例变量来绑定一个用来存储数据的列表'''self.data = list(iterator)def __repr__(self):'''此方法了为打印此列表的数据'''return 'MyList(%r)' % self.datadef __iter__(self):'''有此方法就是可迭代对象,但要求必须返回迭代器'''print("__iter__方法被调用!")return MyListIterator(self.data)class MyListIterator:'''此类用来创建一个迭代器对象,用此迭代器对象可以迭代访问MyList类型的数据'''def __init__(self, iter_data):self.cur = 0 # 设置迭代器的初始值为0代表列表下标# it_data 绑定要迭代的列表self.it_data = iter_datadef __next__(self):'''有此方法的对象才叫迭代器,此方法一定要实现迭代器协议'''print("__next__方法被调用!")# 如果self.cur已经超出了列表的索引范围就报迭代结束if self.cur >= len(self.it_data):raise StopIteration# 否则尚未迭代完成,需要返回数据r = self.it_data[self.cur] # 拿到要送回去的数self.cur += 1 # 将当前值向后移动一个单位return rmyl = MyList([2, 3, 5, 7]) print(myl)for x in myl:print(x) # 此处可以这样做吗?# it = iter(myl) # x = next(it) # print(x) # x = next(it) # print(x) # x = next(it) # print(x)输出:
MyList([2, 3, 5, 7]) __iter__方法被调用! __next__方法被调用! 2 __next__方法被调用! 3 __next__方法被调用! 5 __next__方法被调用! 7 __next__方法被调用!总结
以上是生活随笔为你收集整理的python基础教程:多态、多继承、函数重写、迭代器详细教程的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 零基础学Python:函数的参数详解
- 下一篇: Python中最重要的知识点:切片的操作