




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Ch09类和对象本章要点:9.1面向对象概念9.2类对象和实例对象9.3属性9.4方法9.5继承9.6对象的特殊方法9.7对象的引用、浅拷贝和深拷贝9.8可迭代对象:迭代器和生成器9.9自定义类应用举例资源下载提示2课件等资源:扫描封底的“课件下载”二维码,在公众号“书圈”中下载。素材(源码):扫描本书目录上方的二维码下载。讲解视频:扫描封底刮刮卡中的二维码,再扫描书中相应章节中(位于每章最前)的二维码,作为开源的补充阅读和学习资源。
案例研究:扫描封底刮刮卡中的二维码,再扫描书中相应章节中(位于每章最后)的二维码,可以在线学习。每章练习题:扫描封底刮刮卡中的二维码,再扫描每章习题部分的二维码,下载本章练习题电子版。
题库平台:教师登录网站(),联系客服开通教师权限面向对象概念封装、继承和多态对象的定义某种事物的抽象(功能)抽象原则包括数据抽象和过程抽象两个方面数据抽象-定义对象属性;过程抽象-定义对象操作封装把客观事物抽象并封装成对象继承允许使用现有类的功能,并在无需重新改写原来的类的情况下,对这些功能进行扩展多态性:对象可以表示多个类型的能力类和对象类与对象的关系~车型设计和具体的车类的声明【例9.1】定义类Person1(Person1.py)对象的创建和使用【例9.2】实例对象的创建和使用示例classPerson1:#定义类Person1pass#类体为空语句#测试代码p1=Person1()#创建和使用类对象print(Person1,type(Person1),id(Person1))print(p1,type(p1),id(p1))>>>c1=complex(1,2)>>>c1.conjugate()#输出:(1-2j)(1-2j)>>>c1.real#输出:1.01.0属性(1)类中定义的成员变量实例属性通过self.变量名定义的属性【例9.3】定义类Person2。定义成员变量(域)classPerson2:#定义类Person2def__init__(self,name,age):#__init__方法=name#初始化,即成员变量name(域)self.age=age#初始化self.age,即成员变量age(域)defsay_hi(self):#定义类Person2的函数say_hi()print('您好,我叫',)#在实例方法中通过读取成员变量name(域)#测试代码p1=Person2('张三',25)#创建对象p1.say_hi()#调用对象的方法print(p1.age)#通过p1.age(obj1.变量名)读取成员变量age(域)属性(2)类属性:类本身的变量【例9.4】定义类Person3。定义类域和类方法classPerson3:count=0#定义属性count,表示计数name="Person"#定义属性name,表示名称#测试代码Person3.count+=1#通过类名访问,将计数加1print(Person3.count)#类名访问,读取并显示类属性print(P)#类名访问,读取并显示类属性p1=Person3()#创建实例对象1p2=Person3()#创建实例对象2print((,))#通过实例对象访问,读取成员变量的值P="雇员"#通过类名访问,设置类属性值print((,))#读取成员变量的值="员工"#通过实例对象访问,设置实例对象成员变量的值print((,))#读取成员变量的值属性(3)私有属性和公有属性两个下划线开头,但是不以两个下划线结束的属性是私有的(private),其他为公共的(public)【例9.5】私有属性示例(private.py)classA:__name='classA'#私有类属性defget_name():print(A.__name)#在类方法中访问私有类属性#测试代码A.get_name()A.__name#导致错误,不能直接访问私有类属性属性(4)@property装饰器【例9.6】property装饰器示例1classPerson11:def__init__(self,name):self.__name=name@propertydefname(self):returnself.__name#测试代码p=Person11('王五')print()属性(5)【例9.7】property装饰器示例2classPerson12:def__init__(self,name):self.__name=name@propertydefname(self):returnself.__name@name.setterdefname(self,value):self.__name=value@name.deleterdefname(self):delself.__name#测试代码p=Person12('姚六')='王依依'print()属性(6)【例9.8】property装饰器示例3classPerson13:def__init__(self,name):self.__name=namedefgetname(self):returnself.__namedefsetname(self,value):self.__name=valuedefdelname(self):delself.__namename=property(getname,setname,delname,"I'mthe'name'property.")#测试代码p=Person13('爱丽丝');print()='罗伯特';print()属性(7)特殊属性(SpecialAttributes)表9-1Python特殊属性自定义属性(CustomAttributes)【例9.9】自定义属性示例classCustomAttribute(object):def__init__(self):passdef__getattribute__(self,name):returnstr.upper(object.__getattribute__(self,name))def__setattr__(self,name,value):object.__setattr__(self,name,str.strip(value))#测试代码o=CustomAttribute()o.firstname='mary'print(o.firstname)方法【例9.10】实例方法示例。定义类Person4,创建其对象,并调用对象函数classPerson4:#定义类Person4defsay_hi(self,name):#定义方法say_hi=name#把参数name赋值给,即成员变量name(域)print('您好,我叫',)p4=Person4()#创建对象实例p4.say_hi('Alice')#调用对象实例的方法静态方法(@staticmethod)声明属于与类的对象实例无关的方法静态方法不对特定实例进行操作,在静态方法中访问对象实例会导致错误静态方法通过装饰器@staticmethod来定义静态方法一般通过类名来访问,也可以通过对象实例来调用【例9.11】静态方法示例(TemperatureConverter.py)classTemperatureConverter:@staticmethoddefc2f(t_c):#摄氏温度到华氏温度的转换t_c=float(t_c)t_f=(t_c*9/5)+32returnt_f@staticmethoddeff2c(t_f):#华氏温度到摄氏温度的转换t_f=float(t_f)t_c=(t_f-32)*5/9returnt_c#测试代码print("1.从摄氏温度到华氏温度.")print("2.从华氏温度到摄氏温度.")choice=int(input("请选择转换方向:"))ifchoice==1:t_c=float(input("请输入摄氏温度:"))t_f=TemperatureConverter.c2f(t_c)print("华氏温度为:{0:.2f}".format(t_f))elifchoice==2:t_f=float(input("请输入华氏温度:"))t_c=TemperatureConverter.f2c(t_f)print("摄氏温度为:{0:.2f}".format(t_c))else:print("无此选项,只能选择1或2!")摄氏温度与华氏温度之间的相互转换类方法(@classmethod)允许声明属于类本身的方法,即类方法类方法不对特定实例进行操作,在类方法中访问对象实例属性会导致错误类方法通过装饰器@classmethod来定义,第一个形式参数必须为类对象本身,通常为cls类方法一般通过类名来访问,也可通过对象实例来调用【例9.12】类方法示例classFoo:classname="Foo"def__init__(self,name):=namedeff1(self):#实例方法
print()@staticmethoddeff2():#静态方法
print("static")@classmethoddeff3(cls):#类方法
print(cls.classname)#测试代码f=Foo("李")f.f1()Foo.f2()Foo.f3()__init__方法(构造函数)和__new__方法__init__方法即构造函数(构造方法),用于执行类的实例的初始化工作。创建完对象后调用,初始化当前对象的实例,无返回值__new__方法是一个类方法,创建对象时调用,返回当前对象的一个实例,一般无需重载该方法【例9.13】__init__方法示例1(PersonInit.py)classPerson5:#定义类Person5def__init__(self,name):#__init__方法=name#把参数name赋值给,即成员变量name(域)defsay_hi(self):#定义类Person的方法say_hiprint('您好,我叫',)p5=Person5('Helen')#创建对象p5.say_hi()#调用对象的方法【例9.14】__init__方法示例2定义类Point,表示平面坐标点classPoint:def__init__(self,x=0,y=0):#构造函数self.x=xself.y=yp1=Point()#创建对象print("p1({0},{1})".format(p1.x,p1.y))p1=Point(5,5)#创建对象print("p1({0},{1})".format(p1.x,p1.y))__del__方法(析构函数)__del__方法即析构函数(析构方法),用于实现销毁类的实例所需的操作,如释放对象占用的非托管资源(例如:打开的文件、网络连接等)默认情况下,当对象不再被使用时,__del__方法运行,由于Python解释器实现自动垃圾回收,即无法保证这个方法究竟在什么时候运行通过del语句,可以强制销毁一个对象实例,从而保证调用对象实例的__del__方法【例9.15】__del__方法示例classPerson3:count=0#定义类域count,表示计数def__init__(self,name,age):#构造函数=name#把参数name赋值给,即成员变量name(域)self.age=age#把参数age赋值给self.age,即成员变量age(域)Person3.count+=1#创建一个实例时,计数加1def__del__(self):#析构函数Person3.count-=1#销毁一个实例时,计数减1defsay_hi(self):#定义类Person3的方法say_hi()print('您好,我叫',)defget_count():#定义类Person3的方法get_count()print('总计数为:',Person3.count)print('总计数为:',Person3.count)#类名访问p31=Person3('张三',25)#创建对象p31.say_hi()#调用对象的方法Person3.get_count()#通过类名访问p32=Person3('李四',28)#创建对象p32.say_hi()#调用对象的方法Person3.get_count()#通过类名访问delp31#删除对象p31Person3.get_count()#通过类名访问delp32#删除对象p32Person3.get_count()#通过类名访问私有方法与公有方法两个下划线开头,但不以两个下划线结束的方法是私有的(private),其他为公共的(public)以双下划线开始和结束的方法是Python的专有特殊方法。不能直接访问私有方法,但可以在其他方法中访问【例9.16】私有方法示例classBook:#定义类Bookdef__init__(self,name,author,price):=name#把参数name赋值给,即成员变量name(域)self.author=author#把参数author赋值给self.author,即成员变量author(域)self.price=price#把参数price赋值给self.price,即成员变量price(域)def__check_name(self):#定义私有方法,判断name是否为空if=='':returnFalseelse:returnTruedefget_name(self):#定义类Book的方法get_nameifself.__check_name():print(,self.author)#调用私有方法else:print('Novalue')b=Book('Python程序设计教程','江红',59.0)#创建对象b.get_name()
#调用对象的方法b.__check_name()#直接调用私有方法,非法方法重载Python本身是动态语言,方法的参数没有声明类型(在调用传值时确定参数的类型),参数的数量由可选参数和可变参数来控制。故Python对象方法不需要重载,定义一个方法即可实现多种调用,从而实现相当于其他程序设计语言的重载功能【例9.17】方法重载示例1(Person21Overload.py)classPerson21:#定义类Person21defsay_hi(self,name=None):#定义类方法say_hi=name#把参数name赋值给,即成员变量name(域)ifname==None:print('您好!')else:print('您好,我叫',)p21=Person21()
#创建对象p21.say_hi()
#调用对象的方法,无参数p21.say_hi('威尔逊')#调用对象的方法,带参数【例9.18】方法重载示例2classPerson22:
#定义类Person22defsay_hi(self,name):#定义类方法say_hi,带两个参数print('您好,我叫',)defsay_hi(self,name,age):#定义类方法say_hi,带三个参数print('hi,{0},年龄:{1}'.format(name,age))p22=Person22()
#创建对象p22.say_hi('Lisa',22)
#调用对象的方法#p22.say_hi('Bob')
#TypeError:say_hi()missing1requiredpositionalargument:'age'在Python类体中可以定义多个重名的方法,虽然不会报错,但只有最后一个方法有效,所以建议不要定义重名的方法继承派生类:Python支持多重继承,即一个派生类可以继承多个基类声明派生类时,必须在其构造函数中调用基类的构造函数【例9.19】派生类示例创建基类Person,包含两个数据成员name和age;创建派生类Student,包含一个数据成员stu_idclassPerson:#基类def__init__(self,name,age):#构造函数=name#姓名self.age=age#年龄defsay_hi(self):#定义基类方法say_hiprint('您好,我叫{0},{1}岁'.format(,self.age))classStudent(Person):#派生类def__init__(self,name,age,stu_id):#构造函数Person.__init__(self,name,age)#调用基类构造函数self.stu_id=stu_id#学号defsay_hi(self):#定义派生类方法say_hiPerson.say_hi(self)#调用基类方法say_hiprint('我是学生,我的学号为:',self.stu_id)p1=Person('张王一',33)#创建对象p1.say_hi()s1=Student('李姚二',20,'2018101001')#创建对象s1.say_hi()查看继承的层次关系通过类的方法mro()或类的属性__mro__可以输出其继承的层次关系【例9.20】查看类的继承关系示例>>>classA:pass>>>classB(A):pass>>>classC(B):pass>>>classD(A):pass>>>classE(B,D):pass>>>D.mro()[<class'__main__.D'>,<class'__main__.A'>,<class'object'>]>>>E.__mro__(<class'__main__.E'>,<class'__main__.B'>,<class'__main__.D'>,<class'__main__.A'>,<class'object'>)类成员的继承和重写通过继承,派生类继承基类中除构造方法之外的所有成员如果在派生类中重新定义从基类继承的方法,则派生类中定义的方法覆盖从基类中继承的方法【例9.21】类成员的继承和重写示例classDimension:#定义类Dimensionsdef__init__(self,x,y):#构造函数self.x=x#x坐标self.y=y#y坐标defarea(self):#基类的方法area()passclassCircle(Dimension):#定义类Circle(圆)def__init__(self,r):#构造函数Dimension.__init__(self,r,0)defarea(self):#覆盖基类的方法area()return3.14*self.x*self.x#计算圆面积classRectangle(Dimension):#定义类Rectangle(矩形)def__init__(self,w,h):#构造函数Dimension.__init__(self,w,h)defarea(self):#覆盖基类的方法area()returnself.x*self.y#计算矩形面积d1=Circle(2.0)#创建对象:圆d2=Rectangle(2.0,4.0)#创建对象:矩形print(d1.area(),d2.area())#计算并打印圆和矩形面积对象的特殊方法包含许多以双下划线开始和结束的方法,称之为特殊方法例如,创建对象实例时自动调用其__init__方法,a<b时,自动调用对象a的__lt__方法表9-2Python特殊方法【例9.22】对象的特殊方法示例classPerson:def__init__(self,name,age):#特殊方法(构造函数)=nameself.age=agedef__str__(self):#特殊方法,输出成员变量return'{0},{1}'.format(,self.age)#测试代码p1=Person('张三',23)print(p1)运算符重载与对象的特殊方法Python的运算符实际上是通过调用对象的特殊方法实现的表9-3运算符与对应的特殊方法>>>x=12;y=23>>>x+y#等价于调用x.__add__(y)。输出:3535>>>x.__add__(y)#输出:3535【例9.23】运算符重载示例classMyList:#定义类MyListdef__init__(self,*args):#构造函数self.__mylist=[]#初始化私有属性,空列表forarginargs:self.__mylist.append(arg)def__add__(self,n):#重载运算符"+",每个元素增加nforiinrange(0,len(self.__mylist)):self.__mylist[i]+=ndef__sub__(self,n):#重载运算符"-",每个元素减少nforiinrange(0,len(self.__mylist)):self.__mylist[i]-=ndef__mul__(self,n):#重载运算符"*",每个元素乘以nforiinrange(0,len(self.__mylist)):self.__mylist[i]*=ndef__truediv__(self,n):#重载运算符"/",每个元素除以nforiinrange(0,len(self.__mylist)):self.__mylist[i]/=ndef__len__(self):#对应于内置函数len(),返回列表长度return(len(self.__mylist))def__repr__(self):#对应于内置函数str(),显示列表str1=''foriinrange(0,len(self.__mylist)):str1+=str(self.__mylist[i])+''returnstr1#测试代码m=MyList(1,2,3,4,5)#创建对象m+2;print(repr(m))#每个元素加2m-1;print(repr(m))#每个元素减1m*4;print(repr(m))#每个元素乘4m/2;print(repr(m))#每个元素除2print(len(m))#列表长度@functools.total_ordering装饰器支持大小比较的对象需要实现特殊方法:__eq__、__lt__、__le__、__ge__、__gt__使用functools模块的total_ordering装饰器装饰类,则只需要实现__eq__,以及__lt__、__le__、__ge__、__gt__中的任意一个total_ordering装饰器实现其他比较运算,以简化代码量【例9.24】total_ordering装饰器函数示例importfunctools@functools.total_orderingclassStudent:def__init__(self,firstname,lastname):#姓和名self.firstname=firstnameself.lastname=lastnamedef__eq__(self,other):#判断姓名是否一致return((self.lastname.lower(),self.firstname.lower())==(other.lastname.lower(),other.firstname.lower()))def__lt__(self,other):#self姓名<other姓名return((self.lastname.lower(),self.firstname.lower())<(other.lastname.lower(),other.firstname.lower()))#测试代码if__name__=='__main__':s1=Student('Mary','Clinton')s2=Student('Mary','Clinton')s3=Student('Charlie','Clinton')print(s1==s2)print(s1>s3)__call__方法和可调用对象(callable)Python类体中可以定义一个特殊的方法:__call__方法定义了__call__方法的对象称之为可调用对象(callable),即该对象可以像函数一样被调用【例9.25】可调用对象示例classGDistance:#类:自由落体距离def__init__(self,g):#构造函数self.g=gdef__call__(self,t):#自由落体下落距离return(self.g*t**2)/2#测试代码if__name__=='__main__':e_gdist=GDistance(9.8)#地球上的重力加速度fortinrange(11):#自由落体0~10秒的下落距离print(format(e_gdist(t),"0.2f"),end='')#调用可调用对象e_gdist对象的引用、浅拷贝和深拷贝对象的引用:对象的赋值【例9.26】对象的引用示例。若银行卡采用列表[户主名,[卡种别,金额]]表示,则:对象的浅拷贝对象的赋值引用同一个对象,即不拷贝对象切片操作。例如,acc11[:]。对象实例化。例如,list(acc11)。copy模块的copy函数。例如,copy.copy(acc1)。>>>acc10=['Charlie',['credit',0.0]]#创建列表对象(信用卡账户),变量acc10代表主卡>>>acc11=acc10
#变量acc11代表副卡,指向acc10(主卡)的对象>>>id(acc10),id(acc11)
#二者id相同,输出:(2739033039112,2739033039112)【例9.27】对象的浅拷贝示例>>>importcopy>>>acc1=['Charlie',['credit',0.0]]>>>acc2=acc1[:]#使用切片方式拷贝对象>>>acc3=list(acc1)#使用对象实例化方法拷贝对象>>>acc4=copy.copy(acc1)#使用copy.copy函数拷贝对象>>>id(acc1),id(acc2),id(acc3),id(acc4)#拷贝对象id各不相同(2739033039240,2739033040008,2739035724168,2739033039880)>>>acc2[0]='Mary'#acc2的第一个元素赋值,即户主为'Mary'>>>acc2[1][1]=-99.9#acc2的第二个元素的第二个元素赋值,即消费金额99.9>>>acc1,acc2#注意,acc2消费金额改变99.9,acc1也随之改变(['Charlie',['credit',-99.9]],['Mary',['credit',-99.9]])>>>id(acc1[1]),id(acc2[1])#acc1[1]和acc2[1]指向同一个对象(2739033038152,2739033038152)对象的深拷贝使用copy模块的deepcopy函数,拷贝对象中包含的子对象【例9.28】对象的深拷贝示例>>>importcopy>>>acc1=['Charlie',['credit',0.0]]>>>acc5=copy.deepcopy(acc1)#使用copy.deepcopy函数深拷贝对象>>>acc5[0]='Clinton'#acc5的第1个元素赋值,即户主为'Clinton'>>>acc5[1][1]=-19.9#acc5的第2个元素的第2个元素赋值,即消费金额19.9>>>acc1,acc5(['Charlie',['credit',0.0]],['Clinton',['credit',-19.9]])>>>id(acc1),id(acc5),id(acc1[1]),id(acc5[1])(2739033040648,2739033040264,2739033040520,2739033039688)可迭代对象:迭代器和生成器可循环迭代的对象称之为可迭代对象,迭代器和生成器函数是可迭代对象,Python提供了定义迭代器和生成器的协议和方法相对于序列,可迭代对象仅在迭代时产生数据,故可节省内存空间。Python语言提供了若干内置可迭代对象:range、map、filter、enumerate、zip;标准库itertools模块中包含各种迭代器。这些迭代器非常高效,且内存消耗小可迭代对象(Iterable)实现了__iter__()的对象是可迭代对象(iterable)collections.abc模块中定义了抽象基类Iterable,使用内置的isinstance,可判断一个对象是否为可迭代对象系列对象都是可迭代对象,生成器函数和生成器表达式也是可迭代对象>>>importcollections.abc>>>isinstance((1,2,3),collections.abc.Iterable)
#True>>>isinstance('python33',collections.abc.Iterable)#True>>>isinstance(123,collections.abc.Iterable)
#False迭代器(Iterator)实现了__next()__的对象是迭代器,可以使用内置函数next(),调用迭代器的__next__()方法,依次返回下一个项目值使用迭代器可以实现对象的迭代循环,迭代器让程序更加通用、优雅、高效,更加Python化>>>importcollections.abc>>>i1=(i**2foriinrange(10))>>>isinstance(i1,collections.abc.Iterator)True迭代器协议迭代器对象必须实现两个方法:__iter__()和__next()__,二者合称为迭代器协议。__iter__()用于返回对象本身,以方便for语句进行迭代,__next()__用于返回下一元素>>>i1=(i**2foriinrange(10))>>>help(i1)…(略)|__iter__(...)|x.__iter__()<==>iter(x)|__next__(...)|x.__next__()<==>next(x)…(略)可迭代对象的迭代:iter函数和next函数使用内置函数iter(iterable),可以返回可迭代对象iterable的迭代器;使用内置函数next(),可以依次返回迭代器对象的下一个项目值【例9.29】使用while循环迭代可迭代对象(while.py)t=(1,2,3,4,5,6,7,8,9,0)#元组fetch=iter(t)
#获取迭代器whileTrue:try:i=next(fetch)exceptStopIteration:breakprint(i,end='')可迭代对象的迭代:for语句使用for语句实现可迭代对象的迭代>>>i1=(1,2,3,4,5,6,7,8,9,0)#元组>>>foriini1:print(i,end='')1234567890
>>>i2=[1,2,3,4,5,6,7,8,9,0]#列表>>>foriini2:print(i,end='')1234567890>>>i3='python33'#字符串>>>foriini3:print(i,end='')python33>>>i4=range(10)#可迭代对象>>>foriini4:print(i,end='')0123456789自定义可迭代对象和迭代器声明一个类,定义__iter__方法和__next()__。创建该类的对象,即是可迭代对象,也是迭代器【例9.30】定义类Fib,实现Fibonacci数列(fibonacciIterNext.py)。Fib对象定义了__iter__方法和__next()__,所以是可迭代对象,也是迭代器classFib:def__init__(self):self.a,self.b=0,1#前两项值def__next__(self):self.a,self.b=self.b,self.a+self.breturnself.a#f(n)=f(n-1)+f(n-2)def__iter__(self):returnself#测试代码fibs=Fib()forfinfibs:iff<1000:print(f,end=',')else:break生成器函数生成器函数使用yield语句返回一个值,然后保存当前函数整个执行状态,等待下一次调用生成器函数是一个迭代器,是可迭代对象,支持迭代>>>defgentripls(n):
foriinrange(n):
yieldi*3>>>f=gentripls(10)>>>f
<generatorobjectgentriplsat0x000001ED6C57DA20>>>>i=iter(f)#通过内置函数iter获得iterator>>>next(i)#通过内置函数next获得下一个项目:0>>>next(i)#通过内置函数next获得下一个项目:3>>>fortinf:print(t,end='')69121518212427【例9.31】利用生成器函数创建Fibonacci数列deffib():a,b=0,1#前两项值while1:a,b=b,a+byielda#f(n)=f(n-1)+f(n-2)#测试代码if__name__=='__main__':fibs=fib()forfinfibs:iff<1000:print(f,end=',')else:break【例9.32】利用生成器函数创建小于m到n之间的素数生成器importmathdefis_prime(n):ifn<2:returnFalseifn==2:returnTrueifn%2==0:returnFalsesqrt_n=int(math.floor(math.sqrt(n)))foriinrange(3,sqrt_n+1,2):ifn%i==0:returnFalsereturnTruedefprimes(m,n):"""返回[m,n]之间所有素数的生成器"""foriinrange(m,n+1):ifis_prime(i):yieldi#测试代码if__name__=='__main__':pimes1=primes(5000000000,5000000090)#pimes1=primes(1,100)forpinpimes1:print(p,end=',')反向迭代:reversed迭代器使用内置函数reversed(),可以实现一个系列的反向系列。如果一个可迭代对象实现了__reversed__()方法,则可以使用reversed()函数获得其反向可迭代对象【例9.33】可反向迭代的迭代器示例(reversedCountdown.py)classCountdown:def__init__(self,start):self.start=start#正向迭代def__iter__(self):n=self.startwhilen>0:yieldnn-=1#反向迭代def__reversed__(self):n=1whilen<=self.start:yieldnn+=1#测试代码if__name__=='__main__':#如果独立运行时,则运行测试代码foriinCountdown(10):print(i,end='')foriinreversed(Countdown(10)):print(i,end='')生成器表达式生成器表达式的语法和列表解析基本一样,只不过生成器表达式使用()代替[]表达式expr使用每次迭代内容iter_var,计算生成一个列表。如果指定了条件表达式cond_expr,则只有满足条件的iterable元素参与迭代>>>(i**2foriinrange(10))<generatorobject<genexpr>at0x000001ED6C57DA98>>>>forjin(i**2foriinrange(10)):
print(j,end='')0149162536496481>>>forjin(iforiinrange(10)ifi%2==0):
print(j,end='')02468range可迭代对象迭代时产生指定范围的数字序列,故可以节省内存空间【例9.34】range可迭代对象示例>>>range
<class'range'>>>>foriinrange(1,10):print(i,end=',')#循环输出可迭代对象的内容1,2,3,4,5,6,7,8,9,>>>list(range(1,10,2))#把可迭代对象转换为列表输出[1,3,5,7,9]map迭代器和itertools.starmap迭代器map是可迭代对象,使用指定函数处理可迭代对象的每个元素(如果函数需要多个参数,则对应各可迭代对象),返回结果可迭代对象【例9.35】map迭代器示例>>>map
<class'map'>>>>list(map(abs,(1,-2,3)))
[1,2,3]>>>importoperator>>>list(map(operator.add,(1,2,3),(1,2,3)))
[2,4,6]如果函数的参数为元组,则需要使用itertools.starmap迭代器【例9.36】itertools.starmap迭代器示例>>>importitertools>>>list(itertools.starmap(pow,[(2,5),(3,2),(10,3)]))[32,9,1000]filter迭代器和itertools.filterfalse迭代器filter是可迭代对象,使用指定函数处理可迭代对象的每个元素,函数返回bool类型的值。若结果为True,则返回该元素。如果function为None,则返回元素为True的元素【例9.37】filter迭代器示例>>>filter
<class'filter'>>>>list(filter(lambdax:x>0,(-1,2,-3,0,5)))
[2,5]>>>list(filter(None,(1,2,3,0,5)))
[1,2,3,5]如果需要返回结果为False的元素,则需要使用itertools.filterfalse迭代器filterfalse根据条件函数predicate处理可迭代对象的每个元素,若结果为True,则丢弃;否则返回该元素>>>importitertools>>>list(itertools.filterfalse(lambdax:x%2,range(10)))[0,2,4,6,8]zip迭代器和itertools.zip_longest迭代器zip是可迭代对象,拼接多个可迭代对象iter1、iter2…的元素,返回新的可迭代对象,其元素为各系列iter1、iter2…对象元素组成的元组。如果各系列iter1、iter2…的长度不一致,则截断至最小系列长度。可以节省内存空间【例9.38】zip迭代器示例>>>zip
#<class'zip'>>>>zip((1,2,3),'abc',range(3))
#<zipobjectat0x000001ED6C5A72C8>>>>list(zip((1,2,3),'abc',range(3)))#[(1,'a',0),(2,'b',1),(3,'c',2)]>>>list(zip('abc',range(10)))
#[('a',0),('b',1),('c',2)]多个可迭代对象的元素个数不一致时,如果需要取最大的长度,则需要使用itertools.zip_longest迭代器【例9.39】itertools.zip_longest迭代器示例>>>importitertools>>>list(itertools.zip_longest('ABCD','xy',fillvalue='-'))[('A','x'),('B','y'),('C','-'),('D','-')]enumerate迭代器enumerate是可迭代对象,用于枚举可迭代对象iterable中的元素,返回元素为元组(计数,元素)的可迭代对象【例9.40】enumerate迭代器示例1>>>enumerate
<class'enumerate'>>>>list(enumerate('ABCD',start=10001))[(10001,'A'),(10002,'B'),(10003,'C'),(10004,'D')]【例9.41】enumerate迭代器示例2(enumerate_lineno.py)。打印文本文件的行号和内容defprintfilewithlineno(path):withopen(path,'r',encoding='utf8')asf:lines=f.readlines()foridx,lineinenumerate(lines):print(idx,line)#测试代码if__name__=='__main__':thisfile=__file__printfilewithlineno(thisfile)无穷系列迭代器itertools.count、cycle和repeat【例9.42】无穷系列迭代器itertools.count、cycle和repeat示例>>>fromitertoolsimport*>>>list(zip(count(1),'abcde'))[(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e')]>>>list(zip(range(10),cycle('abc')))[(0,'a'),(1,'b'),(2,'c'),(3,'a'),(4,'b'),(5,'c'),(6,'a'),(7,'b'),(8,'c'),(9,'a')]>>>list(repeat('God',5))['God','God','God','God','God']itertools模块包含三个无穷系列的迭代器:count(start=0,step=1)#从start开始,步长为step的无穷系列cycle(iterable)#可迭代对象iterable元素的无限重复repeat(object[,times])#重复对象object无数次(若指定times,则重复times次)累计迭代器itertools.accumulateitertools模块的accumulate迭代器用于返回累计和【例9.43】累计迭代器itertools.accumulate示例>>>importitertools>>>list(accumulate((1,2,3,4,5)))#结果元素为1、1+2、1+2+3、…,即[1,3,6,10,15]>>>list(accumulate((1,2,3,4,5),operator.mul))#使用乘法作为运算,结果为[1,2,6,24,120]级联迭代器itertools.chainitertools模块的chain迭代器用于返回级联元素【例9.44】级联迭代器chain示例>>>importitertools>>>list(itertools.chain((1,2,3),'abc',range(5)))[1,2,3,'a','b','c',0,1,2,3,4]>>>list(itertools.chain.from_iterable(['ABC','DEF']))['A','B','C','D','E','F']选择压缩迭代器presscompress迭代器用于返回可迭代对象的部分元素根据选择器selectors的元素(True/False),返回元素为True对应的data系列中的元素。当data系列或selectors终止时,停止判断【例9.45】选择压缩迭代器press示例>>>importitertools>>>list(press('ABCDEF',[1,0,1,0,1,1]))['A','C','E','F']截取迭代器itertools.dropwhile和takewhile用于返回可迭代对象的部分元素dropwhile根据条件函数predicate处理可迭代对象的每个元素,丢弃iterable的元素,直至条件函数的结果为True;takewhile则根据条件函数predicate处理可迭代对象的每个元素,返回iterable的元素,直至条件函数的结果为False【例9.46】截取迭代器itertools.dropwhile和takewhile示例>>>importitertools>>>list(itertools.dropwhile(lambdax:x<5,[1,4,6,4,1]))[6,4,1]>>>list(itertools.takewhile(lambdax:x<5,[1,4,6,4,1]))[1,4]切片迭代器itertools.islice从索引位置start(第1个元素为0)开始,到stop(不包括)结束,步长为step(默认为1)【例9.47】切片迭代器itertools.islice示例>>>importitertools>>>list(itertools.islice('ABCDEFG',2))['A','B']>>>list(itertools.islice('ABCDEFG',2,4))['C','D']>>>list(itertools.islice('ABCDEFG',2,None))['C','D','E','F','G']>>>list(itertools.islice('ABCDEFG',0,None,2))['A','C','E','G']分组迭代器itertools.groupbygroupby返回的结果为迭代器,其元素为(key,group),其中key是分组的键值,group为iterable中具有相同key值的元素的集合的子迭代器【例9.48】分组迭代器itertools.groupby示例>>>importitertools>>>data=[1,-2,0,0,-1,2,1,-1,2,0,0];data1=sorted(data,key=abs)>>>fork,ginitertools.groupby(data1,key=abs):
print(k,list(g))0[0,0,0,0]1[1,-1,1,-1]2[-2,2,2]返回多个迭代器itertools.teeitertools模块的tee迭代器用于返回多个可迭代对象:tee(iterable,n=2)#构造函数返回可迭代对象iterable的n个(默认为2)迭代器>>>importitertools>>>foriinitertools.tee(range(10),3):print(list(i))[0,1,2,3,4,5,6,7,8,9][0,1,2,3,4,5,6,7,8,9][0,1,2,3,4,5,6,7,8,9]组合迭代binations,combinations_with_replacement【例9.49】组合迭代器binations和combinations_with_replacement示例>>>importitertools>>>list(binations([1,2,3],2))[(1,2),(1,3),(2,3)]>>>list(binations([1,2,3,4],2))[(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]>>>list(binations([1,2,3,4],3))[(1,2,3),(1,2,4),(1,3,4),(2,3,4)]>>>list(binations_with_replacement([1,2,3],2))[(1,1),(1,2),(1,3),(2,2),(2,3),(3,3)]itertools模块的combinations(元素不重复)和combinations_with_replacement(元素可重复)迭代器用于系列的组合:combinations(iterable,r)
#构造函数combinations_with_replacement(iterable,r)
#构造函数排列迭代器itertools.permutationsitertools模块的permutations迭代器用于系列的排列:permutations(iterable,r=None)#构造函数返回可迭代对象iterable的元素的排列,组合长度为r(默认为系列长度)【例9.50】排列迭代器itertools.permutations示例>>>importitertools>>>list(itertools.permutations([
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 爱伴我成长感恩教育主题班会
- 2021年重庆市高等职业教育分类考试文化素质真题(中职类)
- 2024年单招数学专项复习试题-数列篇(含答案和解析)
- 顶板管理培训教案
- 青海省西宁市五中、四中、十四中2025年招生全国统一考试仿真卷(二)-高考英语试题仿真试题含解析
- 预防传染病的个人责任与行动
- 河北农业大学现代科技学院《数字信号处理》2023-2024学年第二学期期末试卷
- 2025高考押题范文及题目
- 人教战后资本主义
- 项目施工管理质量管理
- 股骨粗隆间骨折合并下肢静脉血栓的护理查房
- 综采电缆修复工艺
- 汽修维修费用统计表报价单
- 用电量与气温变化关系分析
- GB/T 7113.1-2014绝缘软管第1部分:定义和一般要求
- 水工建筑钢结构钢闸门图文讲义
- 幼儿园《幼小衔接》课件
- 《梅花》 完整版课件
- 房地产抖音短视频培训课件
- 苏教版数学二年级下册《数学绘本:公主殿下来的那一天》区级展示课(定稿)
- 中国传媒大学-导演手册-课件
评论
0/150
提交评论