《Python程序設計與算法基礎教程》課件(含思政案例) Ch09 面向對象程序設計_第1頁
《Python程序設計與算法基礎教程》課件(含思政案例) Ch09 面向對象程序設計_第2頁
《Python程序設計與算法基礎教程》課件(含思政案例) Ch09 面向對象程序設計_第3頁
《Python程序設計與算法基礎教程》課件(含思政案例) Ch09 面向對象程序設計_第4頁
《Python程序設計與算法基礎教程》課件(含思政案例) Ch09 面向對象程序設計_第5頁
已閱讀5頁,還剩72頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論