Python編程基礎(第3版)(微課版)課件 單元5-10 函數- 綜合案例:汽車銷售數據 分析_第1頁
Python編程基礎(第3版)(微課版)課件 單元5-10 函數- 綜合案例:汽車銷售數據 分析_第2頁
Python編程基礎(第3版)(微課版)課件 單元5-10 函數- 綜合案例:汽車銷售數據 分析_第3頁
Python編程基礎(第3版)(微課版)課件 單元5-10 函數- 綜合案例:汽車銷售數據 分析_第4頁
Python編程基礎(第3版)(微課版)課件 單元5-10 函數- 綜合案例:汽車銷售數據 分析_第5頁
已閱讀5頁,還剩337頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

自定義函數1區分局部變量和全局變量目錄嵌套函數2【任務5-1】構建計算用餐總價格的函數3【任務5-2】構建求方差函數4Python允許在函數內部定義另外一個函數,即嵌套函數。定義在其他函數內部的函數稱為內置函數,而包含內置函數的函數稱為外部函數。內置函數中的局部變量獨立于外部函數,如果外部函數想要使用這些變量,那么需要聲明相應變量為全局變量。嵌套函數>>>defmean(*args):#定義求均值函數...m=0...defsum(x):#內建求和函數...sum1=0...foriinx:...sum1+=i...returnsum1...m=sum(args)/len(args)...returnm嵌套函數如果需要定義一個求均值的函數,那么需要先計算數值的和,可以在求均值函數的內部內建求和函數,示例代碼如下。Python也將函數視為對象,因此允許外部函數在返回結果時直接調用內置函數的結果。如下代碼示例,可以簡化求均值函數,令其直接返回求和函數的結果。嵌套函數>>>defmeans(*args):...defsum(x):...sum1=0...foriinx:...sum1+=i...returnsum1...returnsum(args)/len(args)#直接返回求和函數的結果1區分局部變量和全局變量目錄嵌套函數2【任務5-1】構建計算用餐總價格的函數3【任務5-2】構建求方差函數4定義函數時往往需要在函數內部對變量進行定義和賦值,在函數內部定義的變量即局部變量。例如,定義一個求和函數,代碼如下。1.局部變量>>>defsum(*arg):...sum1=0...foriinrange(len(arg)):...sum1+=arg[i]...returnsum1>>>print(sum(1,2,3,4,5))15>>>print(sum1)NameError:name'sum1'isnotdefined與局部變量對應,定義在函數外部的變量即全局變量。全局變量可以在函數內部被調用,代碼如下。2.全局變量>>>sum0=10>>>deffun():...sum_global=sum0+100...returnsum_global>>>print(fun())110全局變量不能在函數內部直接被賦值,否則會報錯,代碼如下。2.全局變量>>>sum1=0>>>defsum(*arg):...foriinrange(len(arg)):...sum1+=arg[i]...returnsum1>>>print(sum(1,2,3,4))UnboundLocalError:cannotaccesslocalvariable'sum1'whereitisnotassociatedwithavalue若同時存在全局變量和局部變量,則函數會使用局部變量對全局變量進行覆蓋,代碼如下。2.全局變量>>>sum1=10>>>defsum(*arg):...sum1=0...foriinrange(len(arg)):...sum1+=arg[i]...returnsum1>>>print(sum(1,3,4,5))13如果想要在函數內部對全局變量賦值,那么需要使用關鍵字global。在嵌套函數中,nonlocal的用法和global類似,示例代碼如下。2.全局變量>>>sum1=0>>>defsum(*arg):...globalsum1...foriinrange(len(arg)):...sum1+=arg[i]...returnsum1>>>print(sum(1,3,5,7))16>>>print(sum1)16>>>print(sum(1,3,5,7))321區分局部變量和全局變量目錄嵌套函數2【任務5-1】構建計算用餐總價格的函數3【任務5-2】構建求方差函數4【任務5-1】構建計算用餐總價格的函數任務分析任務描述為了提高結賬效率并確保交易準確性,收銀員創建了一個名為day_income的函數,該函數能夠根據顧客購買的菜品重量和單價自動計算出總銷售額。(1)創建函數day_income,輸入參數為菜的單價unit_price和不定參數客人的點菜重量列表table_count。(2)使用sum函數計算今日所賣的葷素菜總量。(3)計算當日銷售額(菜的重量×菜的單價),并返回當日銷售額。(4)調用函數day_income,指定當日點菜重量列表為[12,9,7,10,7,6,11,9,8,11],菜的單價為10,輸出當日銷售額。1區分局部變量和全局變量目錄嵌套函數2【任務5-1】構建計算用餐總價格的函數3【任務5-2】構建求方差函數4【任務5-2】構建求方差函數任務分析任務描述方差是統計學中用于衡量數據波動性的關鍵指標,它反映了數據與平均值之間的差異。根據函數構建求方差的函數。(1)構建求和函數sum。(2)構建求均值函數mean,需調用求和函數sum的結果。(3)構建求完全平方差函數sums,需調用求均值函數mean的結果。(4)構建求方差函數var,構建sum函數、mean函數和sums函數,并需調用求完全平方差函數sums的結果。自定義函數1設置函數參數目錄認識自定義函數2函數返回值3調用自定義函數4Python提供了自定義函數的功能。使用def關鍵字可以自定義函數,格式如下。認識自定義函數deffunction(par1,par2,…):suitereturnexpression其中function為函數名,括號內包含將要在函數體中使用的形式參數(簡稱形參),定義語句以冒號結束;suite為函數體,其縮進為4個空格或一個制表符;expression為返回值的表達式。函數定義示例如代碼如下。認識自定義函數>>>defmy_function(parameter):#輸出傳入的任何字符串...print(parameter)#print與return沒有關系,也不會相互影響...return'parameteris'+parameter函數名為my_function,輸入參數是parameter,輸出參數是parameter,返回值是“parameteris”字符串加上parameter參數。1設置函數參數目錄認識自定義函數2函數返回值3調用自定義函數4在Python中,函數參數主要有以下4種。(1)位置參數。調用函數時,根據函數定義的位置參數來傳遞參數。(2)關鍵字參數。關鍵字參數通過“鍵-值”形式加以指定,可以讓函數更加清晰、容易使用,同時也消除了參數的順序要求。(3)默認參數。定義函數時為參數提供了默認值的參數稱為默認參數。在調用函數時,默認參數的值可傳可不傳。需要注意的是,所有的位置參數必須出現在默認參數前。(4)可變參數。當定義函數時,有時候不確定之后調用時會傳遞多少個參數(也可以不傳參數)。此時,可使用定義任意位置參數或關鍵字參數的方法來進行參數傳遞。設置函數參數在調用內置函數時,函數提供了默認參數。下面定義一個計算利息的函數,示例如下。1.默認參數>>>definterest(money,day=1,interest_rate=0.05):...income=money*interest_rate*day/365...print(income)當僅需要計算單日利息時,只需要輸入本金的數值即可,示例如下。>>>print(interest(5000))#本金為5000,年化利率為默認值0.05時的單日利息0.684931506849315>>>print(interest(10000))#本金為10000,年化利率為默認值0.05時的單日利息1.36986301369863定義函數時需要確定函數的參數個數,參數個數表示函數可調用的參數個數的上限。當定義函數時,如果無法確定參數個數,可以使用*args和**kwargs定義可變參數。在定義任意數量的位置可變參數時,參數名前面需要有一個星號(*)作為前綴,在傳遞參數的時候,可以在原有的參數后面添加0個或多個參數,這些參數將會被放在元組中并傳入函數。任意數量的位置可變參數必須定義在位置參數或關鍵字參數之后,示例代碼如下。2.任意數量的位置可變參數>>>defexp(x,y,*args):...print('x:',x)...print('y:',y)...print('args:',args)>>>exp(1,5,66,55,'abc')x:1y:5args:(66,55,'abc')2.任意數量的位置可變參數在定義任意數量的關鍵字可變參數時,參數名前面需要有兩個星號(**)作為前綴。在傳遞參數時,可以在原有的參數后面添加任意數量的關鍵字可變參數,這些參數會被放到字典中并傳入函數,示例代碼如下。任意數量的關鍵字可變參數必須在所有默認參數之后,順序不可以調轉。3.任意數量的關鍵字可變參數3.任意數量的關鍵字可變參數>>>defexp(x,y,*args,**kwargs):...print('x:',x)...print('y:',y)...print('args:',args)...print('kwargs:',kwargs)>>>exp(1,2,2,4,6,a='c',b=1)x:1y:2args:(2,4,6)kwargs:{'a':'c','b':1}1設置函數參數目錄認識自定義函數2函數返回值3調用自定義函數4函數可以處理一些數據,并返回一個或一組值。函數返回的值稱為返回值。需要保存或調用函數的返回值,那么需要使用return語句,示例代碼如下。函數返回值>>>definterest_r(money,day=1,interest_rate=0.05):...income=money*interest_rate*day/365...returnincome函數返回值print函數僅輸出對象,輸出的對象無法保存或被調用,而return語句返回的運行結果可以保存為一個對象供其他函數調用,示例代碼如下。>>>x=interest(1000)0.136986301369863>>>y=interest_r(1000)>>>print(y)0.136986301369863Python對函數返回值的數據結構沒有限制,包括列表和字典等復雜的數據結構。當程序執行到函數中的return語句時,會將指定的值返回并結束函數,return語句后面的語句將不會被執行。1設置函數參數目錄認識自定義函數2函數返回值3調用自定義函數4位置參數調用是最常用的函數調用方式,函數的參數嚴格按照函數定義時的位置傳入,順序不可以調換,否則會影響輸出結果或直接報錯。例如,range函數定義的3個參數start、stop、step需按照順序傳入,示例代碼如下:1.位置參數調用>>>print(list(range(0,10,2)))#按start=0、stop=10、step=2的順序傳入[0,2,4,6,8]>>>print(list(range(10,0,2)))#調換start和stop的順序后傳入[]>>>print(list(range(10,2,0)))#調換全部參數的順序后傳入ValueError:range()arg3mustnotbezero當函數的參數有默認值時,可以不設置相應的函數參數,因為此時的函數會使用默認參數,代碼如下。1.位置參數調用>>>print(list(range(0,10,1)))[0,1,2,3,4,5,6,7,8,9]>>>print(list(range(10)))[0,1,2,3,4,5,6,7,8,9]除了可以使用位置參數對函數進行調用外,還可以使用關鍵字參數對函數進行調用。當使用關鍵字參數時,可以不嚴格按照定義參數時參數的順序傳入值,因為解釋器會自動根據關鍵字進行匹配,示例代碼如下。2.關鍵字參數調用>>>print(interest(money=5000,day=7,interest_rate=0.06))5.7534246575342465>>>print(interest(day=7,money=5000,interest_rate=0.06))5.7534246575342465關鍵字參數也可以與位置參數混用。關鍵字參數必須跟在位置參數后面,否則會報錯,示例代碼如下。2.關鍵字參數調用>>>print(interest(10000,day=7,interest_rate=0.06))11.506849315068493>>>print(interest(10000,interest_rate=0.06,day=7))11.506849315068493>>>#關鍵字參數必須跟在位置參數后面,否則會報錯>>>print(interest(interest_rate=0.06,7,money=10000))SyntaxError:positionalargumentfollowskeywordargument使用*args位置可變參數可以直接將元組或列表轉換為參數,然后傳入函數,示例代碼如下。3.可變參數調用>>>args=[0,10,2]>>>print(list(range(*args)))[0,2,4,6,8]3.可變參數調用使用**kwargs關鍵字可變參數可以直接將字典轉換為關鍵字參數,然后傳入函數中,示例代碼如下。>>>defuser(username,age,**kwargs):...print('username:',username,...'age:',age,...'other:',kwargs)>>>user('john',27,city='guangzhou',job='DataAnalyst')username:johnage:27other:{'city':'guangzhou','job':'DataAnalyst'}>>>kw={'age':27,'city':'guangzhou','job':'DataAnalyst'}>>>user('john',**kw)username:johnage:27other:{'city':'guangzhou','job':'DataAnalyst'}匿名函數1其他常用高階內置函數目錄創建并使用匿名函數2【任務5-3】多種方式實現數據累加3匿名函數是指不使用def語句這樣標準的形式定義一個函數,也就是說函數沒有具體的名稱。使用lambda函數創建匿名函數可以省去定義函數的過程,同時可以避免函數的重復使用。在lambda函數中,冒號前是函數參數,若有多個參數,需使用逗號分隔;冒號后是返回值。使用lambda函數創建的函數沒有具體的名稱。創建函數的示例如下。創建并使用匿名函數>>>example=lambdax:x**3>>>print(example)<function<lambda>at0x0000000029E2DD30>>>>print(example(2))8用lambda函數創建函數時,應該注意以下4點。(1)lambda函數創建的是單行函數,如果需要創建復雜的函數,應使用def關鍵字。(2)lambda函數可以包含多個參數。(3)lambda函數有且只有一個返回值。(4)lambda函數中的表達式不能含有命令,且僅限一個表達式。這是為了避免匿名函數的濫用,過于復雜的匿名函數反而不易于解讀。創建并使用匿名函數Python允許將lambda函數作為對象賦值給變量,然后使用變量名進行調用。例如,在Python的數學庫中只有以自然數e和10為底的對數函數,而使用lambda函數即可創建以指定數為底的對數函數,示例代碼如下。創建并使用匿名函數>>>frommathimportlog#引入Python數學庫的對數函數>>>#此函數用于返回一個以base為底的匿名對數函數>>>defmake_logarithmic_function(base):...returnlambdax:log(x,base)>>>#創建一個以3為底的匿名對數函數,并賦值>>>my_log=make_logarithmic_function(3)>>>#調用匿名對數函數my_log,底數已經設置為3,只需設置真數即可>>>#如果使用log函數,那么需要同時設置真數和底數>>>print(my_log(9))2.01其他常用高階內置函數目錄創建并使用匿名函數2【任務5-3】多種方式實現數據累加3map函數是Python內置的高階函數,它的基本格式為map(func,list)。其中,func表示一個函數,list表示一個序列對象。在執行的時候,map函數把函數func按照從左到右的順序依次作用在list的每個元素上,得到一個新的序列對象并返回。示例代碼如下。1.map函數>>>defadd(x):...x**=3...returnx>>>numbers=list(range(10))>>>num1=list(map(add,numbers))>>>num2=list(map(lambdax:x**3,numbers))#速度快,可讀性高fib函數是一個遞歸函數,最典型的遞歸示例之一是斐波那契數列。根據斐波那契數列的定義,可以直接寫出斐波那契數列遞歸函數。fib函數示例代碼如下。2.fib函數>>>deffib(n):...ifn<=2:...return2...else:...returnfib(n-1)+fib(n-2)>>>f=fib(10)>>>print(f)110在上述代碼中,“fib(n1)+fib(n2)”是調用了fib函數自身而實現遞歸的。為了明確遞歸的過程,介紹其計算過程如下(令n=3)。(1)n=3,調用fib(3),判斷后需計算fib(31)+fib(32)。(2)先看fib(31),即fib(2),返回結果為2。(3)再看fib(32),即fib(1),返回結果也為2。(4)最后計算第(1)步,結果為fib(n1)+fib(n2)=2+2=4,將結果返回。從而得到fib(3)的結果為4。從計算過程可以看出,每個遞歸的步驟都是向著最初的已知條件方向得到結果,然后一層層向上反饋計算結果。2.fib函數filter函數是Python內置的另一個常用的高階函數。filter函數接收一個函數func和一個序列對象list,函數func的作用是對list中的每個元素進行判斷,通過返回True或False來過濾掉不符合條件的元素,將符合條件的元素組成新的序列對象。filter函數示例代碼如下。3.filter函數>>>print(list(filter(lambdax:x%2==1,[1,4,6,7,9,12,17])))[1,7,9,17]>>>s=list(filter(lambdac:c!='o','IlovepythonandR!'))>>>s=''.join(s)#轉換為字符型>>>print(s)IlovepythonandR!1其他常用高階內置函數目錄創建并使用匿名函數2【任務5-3】多種方式實現數據累加3【任務5-3】多種方式實現數據累加任務分析任務描述分別通過自定義函數、匿名函數和map函數實現一組數據的累加。(1)使用def關鍵字定義一個累加函數add。(2)創建一個空列表。(3)使用循環結構foriinrange(10)對列表進行數據累加后的元素添加(list.append())。(4)使用匿名函數代替累加函數,并將計算結果添加至列表。(5)使用map函數快速實現數據的累加,以及列表元素的添加。存儲并導入函數模塊1導入函數目錄存儲并導入整個模塊2指定別名3【任務5-4】實現求方差函數存儲與導入4模塊是最高級別的程序組織單元,它能夠將程序代碼和數據封裝起來以便重用。模塊通常對應Python的腳本文件(.py文件),該文件包含該模塊定義的所有函數和變量。模塊可以被其他程序導入,以便程序使用其中的函數等功能。導入模塊后,在模塊文件中定義的所有變量名都會以被導入模塊對象的成員的形式被調用。存儲并導入整個模塊>>>defmake_steak(d,*other):...'''做一份牛排'''...print('Makeasteakwelldonein%d'%d+'withtheother:')...foroinother:...print('-'+o)存儲并導入整個模塊如果要導入模塊中的函數,那么需要先創建一個模塊。創建一個包含make_steak函數的模塊,代碼如下。將上述代碼塊保存為steak.py,并存放在當前路徑。導入這個模塊,并且調用里面的make_steak函數,代碼如下。存儲并導入整個模塊>>>importsteak>>>steak.make_steak(9,'salad')Makeasteakwelldonein9withtheother:-salad1導入函數目錄存儲并導入整個模塊2指定別名3【任務5-4】實現求方差函數存儲與導入4在Python中,可以導入模塊中的指定函數,且指定函數可以是多個。以steak.py為例,只導入指定函數的操作代碼如下。1.導入指定函數>>>fromsteakimportmake_steak>>>make_steak(9,'salad')Makeasteakwelldonein9withtheother:-salad如果模塊中的函數較多,并需要導入所有函數,那么可以使用星號運算符導入所有函數,代碼如下。2.導入所有函數>>>fromsteakimport*>>>make_steak(9,'salad')Makeasteakwelldonein9withtheother:-salad1導入函數目錄存儲并導入整個模塊2指定別名3【任務5-4】實現求方差函數存儲與導入4如果導入的函數的名稱可能與程序中現有的名稱沖突或名稱太長,那么可以用as語句在導入時給函數指定別名。給make_steak函數指定別名為ms的操作代碼如下。1.指定函數別名>>>fromsteakimportmake_steakasms>>>ms(9,'salad')Makeasteakwelldonein9withtheother:-salad在Python中,可以給模塊指定別名。通過給模塊指定簡短的別名(如給steak模塊指定別名S),能夠方便地調用模塊中的函數。相比類似steak.make_steak的調用方式更為簡潔,指定模塊別名代碼如下。2.指定模塊別名>>>importsteakasS>>>S.make_steak(9,'salad')Makeasteakwelldonein9withtheother:-salad1導入函數目錄存儲并導入整個模塊2指定別名3【任務5-4】實現求方差函數存儲與導入4【任務5-4】實現求方差函數存儲與導入任務分析任務描述將自定義方差函數封裝并命名為var.py。(1)導入封裝好的函數模塊。(2)導入模塊中的特定函數var.var。(3)給函數指定別名fangcha。(5)給函數模塊指定別名V。(6)導入模塊中的所有函數。認識面向對象編程1體會面向對象實例目錄面向對象編程及相關內容2面向對象的優點3何時使用面向對象編程4面向對象編程(Object-OrientedProgramming,OOP)即面向對象程序設計。在面向對象編程中,以類來構造現實世界中的事物和情景,再基于類創建對象來幫助用戶進一步認識、理解、刻畫這些事物和情景。基于類創建的對象都會自動帶有類的屬性和特點,還可以根據實際需要賦予每個對象特有的屬性,這個過程稱為類的實例化。從面向對象的設計(Object-OrientedDesign,OOD)的角度來看,類往往是由現實對象抽象而來的,抽象類可以看作基于類的進一步抽象。從實現角度來看,抽象類與普通類的不同之處在于:抽象類中可以包含抽象方法(沒有實現功能),此類不能被實例化,只能被繼承使用,且子類必須實現其中抽象方法。1.面向對象編程面向對象方法(Object-OrientedMethod,OOM),是在軟件開發過程中以“對象”為中心,用面向對象的思想來指導開發活動的系統方法。正如研究面向對象方法的專家和學者所說,面向對象方法同20世紀70年代的結構化方法一樣,對計算機技術的應用產生了巨大的影響,而且一直在強烈地影響和促進一系列高技術的發展和多學科的融合。2.面向對象方法從20世紀80年代起,面向對象程序設計成了一種主導思想,但一直沒有專門的面向對象程序設計的語言。后因客觀需求的推動,人們進行了大量理論研究和實踐探索,不同類型的面向對象語言(如Eiffel、C++、Java、Object-Pascal等)得以產生和發展,逐步解決了兼容性和維護性等問題。3.面向對象編程語言1體會面向對象實例目錄面向對象編程及相關內容2面向對象的優點3何時使用面向對象編程4面向過程是分析解決問題所需要的步驟,然后用函數一步步實現這些步驟。面向對象是將構成問題的事物分解成各個對象,創建對象是為了描述某個事物在解決問題過程中的行為。例如五子棋,面向過程的設計思路是分析解決問題的步驟,將每個步驟分別用函數來實現,從而使問題得到解決,如下圖。而面向對象的設計則基于以下思路來解決問題:將五子棋分為3類對象,一是黑白雙方,雙方的行為是一模一樣的;二是棋盤系統,負責繪制畫面;三是規則系統,負責判斷諸如犯規、輸贏等。體會面向對象實例可以看到,面向對象是以功能來劃分問題的,而不是循環步驟。同樣是繪制棋局,在面向過程的設計中,需要多個步驟來執行該任務,但這樣很可能會導致不同步驟繪制棋局的程序不同,因此程序設計人員會根據實際情況對繪制棋局的程序進行調整。而在面向對象的設計中,繪圖只可能在第2類對象中出現,由此可以保證繪制棋局程序的統一。體會面向對象實例1體會面向對象實例目錄面向對象編程及相關內容2面向對象的優點3何時使用面向對象編程4面向對象有以下3個優點。(1)基于數據抽象的概念,面向對象可以在保持外部接口不變的情況下對內部進行修改,從而減少甚至避免對外界的干擾。(2)面向對象通過繼承可以大幅減少冗余代碼,并可以方便地擴展現有代碼,提高編碼效率,降低出錯概率及軟件維護難度。(3)結合面向對象分析、面向對象的設計,面向對象允許將問題中的對象直接映射到程序中,簡化了在軟件開發過程中中間環節的轉換過程。面向對象的優點1體會面向對象實例目錄面向對象編程及相關內容2面向對象的優點3何時使用面向對象編程4在人工智能系統中,每個智能體或代理被看作一個類,具體的某個智能體或代理就是其中某個類的一個實例對象,所以每個智能體或代理的程序都具有一定的獨立性。對于小型程序和算法來說,面向對象的程序一般會比面向過程的程序慢,所以編寫程序時需要掌握面向對象和面向過程兩種思想,發揮每種思想的長處。何時使用面向對象編程類1綁定self參數目錄定義和使用類2類的專有方法3【任務6-1】創建Car類4類的定義和函數的定義相似,只是用class關鍵字替代了def關鍵字,同樣,在執行class的整段代碼后,定義的類才會生效。進入類定義部分后,會創建一個新的局部作用域,在后面定義的類中,屬性和方法都是屬于局部作用域的局部變量。類的定義、類的使用定義類的格式如下。class類名:

屬性列表

方法列表當使用class關鍵字創建類時,只要將所需的屬性列表和方法列表列出即可,代碼如下。類的使用>>>classCat:...'''一次模擬貓咪的簡單嘗試'''...#屬性...name='tesila'...age=3...#方法...defsleep(self):...'''模擬貓咪被命令睡覺'''...return'%d歲的%s正在沙發上睡懶覺。'%(self.age,)...defeat(self,food):...'''模擬貓咪被命令吃東西'''...self.food=food...return'%d歲的%s在吃%s。'%(self.age,,self.food)1綁定self參數目錄定義和使用類2類的專有方法3【任務6-1】創建Car類4Python的類的方法和普通的函數有一個很明顯的區別,就是類的方法必須有一個額外的參數self,并且在調用方法的時候不必為這個參數賦值。Python的類的方法的特別參數指代的是對象本身,而按照Python慣例,用self來表示。代碼如下。綁定self參數>>>classCat:...defsleep(self):...print(self)>>>new_cat=Cat()>>>new_cat.sleep()<__main__.Catobjectat0x000002794232A690>self參數代表當前對象的地址,能避免非限定調用時找不到訪問對象或變量。當調用sleep等函數時,會自動將該對象的地址作為第1個參數傳入;如果不傳入地址,程序將不知道該訪問哪個對象。self這一名稱也不是必需的,在Python中,self不是關鍵字,可以將其定義成a、b或其他名字。利用my_address代替self,一樣不會出現錯誤,代碼如下。綁定self參數>>>classTest:...defprt(my_address):...print(my_address)...print(my_address.__class__)>>>t=Test()>>>t.prt()<__main__.Testobjectat0x000002794232AF90><class'__main__.Test'>1綁定self參數目錄定義和使用類2類的專有方法3【任務6-1】創建Car類4任何類都有類的專有方法,它們的特殊性從方法名就能看出,其通常使用雙下畫線“__”開頭和結尾。查看類或對象(實例)的屬性和方法,要通過點號操作來實現,即object.attribute,也可以通過點號操作實現對屬性的修改和增加。查看類的屬性和方法的示例代碼如下。類的專有方法>>>classExample:...pass>>>example=Example()>>>print(dir(example))['__class__','__delattr__','__dict__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__getstate__','__gt__','__hash__','__init__','__init_subclass__','__le__','__lt__','__module__','__ne__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__']定義類時只使用了pass語句,所以列出的結果都是以雙下畫線“__”開頭和結尾的。上面代碼的運行結果可知,使用dir函數可以查看類的屬性和方法。類的常用專有方法如下表。類的專有方法專有方法功

能專有方法功

能__init__構造方法,生成對象時被調用__call__函數調用__del__析構方法,釋放對象時被調用__add__加運算__repr__輸出類的實例化對象__sub__減運算__setitem__按照索引賦值__mul__乘運算__getitem__按照索引獲取值__div__除運算__len__獲得長度__mod__求余運算__cmp__比較運算__pow__冪運算__getitem__和__setitem__和普通的方法clear()、keys()、values()類似,只是重定向到字典,返回字典的值,通常不用直接調用,可以使用相應的語法讓Python來調用__getitem__和__setitem__。__setitem__方法可以讓任何類像字典一樣保存鍵值對。__getitem__方法可以讓任何類表現得像一個序列。__repr__只有當調用repr(instance)時才會被調用。repr函數是一個內置函數,它用于返回對象的可輸出形式字符串。__cmp__在比較類實例中被調用,通常可以通過使用“==”比較任意兩個Python對象,不只是類實例。類的專有方法__len__在調用len(instance)時被調用。len是Python的內置函數,可以返回一個對象的長度,對于字符串對象,返回的是字符個數;對于字典對象,返回的是鍵值對的個數;對于列表或序列,返回的是元素的個數。對于類和對象,定義__len__專有方法,可以自定義長度的計算方式,然后調用len(instance),Python則將調用定義的__len__專有方法。__del__在調用delinstance[key]時被調用,它會從字典中刪除單個元素。__call__方法讓一個類表現得像一個函數,可以直接調用一個類實例。任何定義了__cmp__專有方法的類都可以用“==”進行比較。在類的應用中,最常見的是先將類實例化,再通過實例來執行類的專有方法。類的專有方法1綁定self參數目錄定義和使用類2類的專有方法3【任務6-1】創建Car類4【任務6-1】創建Car類任務分析任務描述創建一個Car類,代表一輛汽車,具有車輪數(4)和顏色(red)的屬性,以及兩個函數:getCarInfo和run。通過實例化Car類并調用其方法,可以看到汽車的基本信息和行駛狀態。(1)使用class語句創建Car類,添加車輪數和顏色兩個屬性。(2)使用def關鍵字定義getCarInfo函數,增加參數name,返回名字、車輪數和顏色3個屬性的字符串。(3)使用def關鍵字定義run函數,返回語句“車行駛在學習的大道上。”。(4)調用Car類賦值于new_car。(5)使用new_car調用getCarInfo函數和run函數。對象1刪除對象目錄創建對象2對象的屬性和方法3【任務6-2】創建Car對象4__init__是類的專有方法,每當根據類創建新實例時,Python都會自動運行__init__。這是一個初始化手段,Python中的__init__方法用于初始化類的實例對象。創建對象的示例代碼如下。創建對象>>>classCat:...'''再次模擬貓咪的簡單嘗試'''...#構造方法...def__init__(self,name,age):...#屬性...=name...self.age=age...defsleep(self):...'''模擬貓咪被命令睡覺'''...return'%d歲的%s正在沙發上睡懶覺。'%(self.age,)...defeat(self,food):...'''模擬貓咪被命令吃東西'''...self.food=food...return'%d歲的%s在吃%s'。%(self.age,,self.food)>>>cat1=Cat('Tom',3)1刪除對象目錄創建對象2對象的屬性和方法3【任務6-2】創建Car對象4刪除對象時,同樣會默認調用一個方法,這個方法為析構方法。__del__也是類的專有方法,當使用del語句刪除對象時,會調用__del__本身的析構函數。當對象在某個作用域中調用完畢,跳出其作用域時,析構函數也會被調用一次,目的是釋放內存空間。使用__del__方法刪除對象的具體示例代碼如下。刪除對象>>>classAnimal:...#構造方法...def__init__(self):...print('---構造方法被調用---')...#析構方法...def__del__(self):...print('---析構方法被調用---')>>>cat=Animal()---構造方法被調用---刪除對象>>>print(cat)<__main__.Animalobjectat0x0000027942380450>>>>delcat---析構方法被調用--->>>print(cat)NameError:name'cat'isnotdefined.1刪除對象目錄創建對象2對象的屬性和方法3【任務6-2】創建Car對象4學習了類的定義過程和方法后,可以嘗試創建具體的對象來進一步學習面向對象程序設計。創建對象的示例代碼如下。對象的屬性和方法classCat:def__init__(self,name,age):=nameself.age=agedefsleep(self):''''模擬貓咪被命令睡覺'''return'%d歲的%s正在沙發上睡懶覺。'%(self.age,)對象的屬性和方法defeat(self,food):'''模擬貓咪被命令吃東西'''self.food=foodreturn'%d歲的%s在吃%s。'%(self.age,,self.food)>>>#創建對象>>>cat1=Cat('Tom',3)>>>cat2=Cat('Jack',4)>>>#訪問對象的屬性>>>print('Cat1的名字為:',對象的屬性和方法Cat1的名字為:Tom>>>print('Cat2的名字為:',)Cat2的名字為:Jack>>>#訪問對象的方法>>>print(cat1.sleep())3歲的Tom正在沙發上睡懶覺。>>>print(cat2.eat('fish'))4歲的Jack在吃fish。對象屬性由類的每個實例對象擁有。因此每個對象有自己對這個域的一份備份,即它們不是共享的。在同一個類的不同實例對象中,即使對象的屬性有相同的名稱,也互不相關。對于類屬性和對象屬性,如果在類方法中引用某個屬性,那么該屬性必定是類屬性。要修改類屬性,如果在類外,那么可以通過類對象修改;如果在類里面,那么只能在類方法中進行修改。1.對象屬性對象方法和類的方法是一樣的。在定義類的方法時,程序沒有為類的方法分配內存,只有在創建具體實例對象時,程序才會為對象的每個數據屬性和方法分配內存。類的方法是由def關鍵字定義的,具體定義格式與普通函數的定義格式相似,只是類的方法的第一個參數需要是self參數。用普通函數可以實現對對象方法的引用,示例代碼如下。2.對象方法>>>cat1=Cat('Tom',3)>>>sleep=cat1.sleep>>>print(sleep())3歲的Tom正在沙發上睡懶覺。>>>cat2=Cat('Jack',4)>>>eat=cat2.eat>>>print(eat('fish'))4歲的Jack在吃fish。如果要獲取上述代碼中對象的數據屬性,并不需要通過sleep、eat等函數,直接在程序外部調用數據屬性即可,示例代碼如下。3.私有化>>>print(cat1.age)3>>>print()Jack盡管直接調用的方法很方便,但是破壞了類的封裝性,這是因為對象的狀態對于類外部而言應該是不可訪問的。為防止程序開發人員在無意中修改對象的狀態,需要對類的數據屬性和方法進行私有化。Python提供了方法以達到私有化的目的。為了讓方法的數據屬性或方法變為私有,只需要在屬性或方法的名字前面加上雙下畫線即可,修改前文創建的Cat類代碼的示例如下。3.私有化>>>classCat:...def__init__(self,name,age):...self.__name=name...self.__age=age...defsleep(self):...return'%d歲的%s正在沙發上睡懶覺。'%(self.__age,self.__name)3.私有化...defeat(self,food):...self.__food=food...return'%d歲的%s在吃%s。'%(self.__age,self.__name,self.__food)...defgetAttribute(self):...returnself.__name,self.__age>>>#創建對象>>>cat1=Cat('Tom',3)>>>cat2=Cat('Jack',4)>>>print('Cat1的名字為:',)#從外部訪問對象的屬性,會發現訪問不了AttributeError:'Cat'objecthasnoattribute'name'3.私有化>>>print('Cat2的名字為:',)AttributeError:'Cat'objecthasnoattribute'name'>>>print(cat1.sleep())#只能通過設置好的接口函數來訪問對象3歲的Tom正在沙發上睡懶覺。>>>print(cat2.eat('fish'))4歲的Jack在吃fish。>>>print(cat1.getAttribute())('Tom',3)在程序外部直接訪問私有化屬性是不允許的,只能通過設置好的接口函數去調取對象的信息。通過雙下畫線實現的私有化其實是“偽私有化”,實際上還是可以從外部訪問這些私有化屬性,示例代碼如下。3.私有化>>>print(cat1._Cat__name)Tom>>>print(cat1._Cat__age)31刪除對象目錄創建對象2對象的屬性和方法3【任務6-2】創建Car對象4【任務6-2】創建Car對象任務分析任務描述在Python編程中,析構函數是一個特殊的方法,用于在對象被銷毀時自動執行清理操作。根據創建的Car類,為其定義一個析構函數。(1)使用class語句創建Car類。(2)將Car類實例化,添加newWheelNuw和newColor兩個屬性。(3)使用def關鍵字定義run函數,用print函數輸出“車在跑,目標:夏威夷。”。(4)用def__del__定義析構方法,用print函數輸出“---析構方法被調用---”。(5)調用Car類,創建對象并命名為BMW。(6)訪問對象屬性,調用run函數,并用print函數輸出。(7)用析構方法刪除BMW,并查看對象是否被刪除。迭代對象1返回迭代器目錄生成迭代器2【任務6-3】迭代Car類3迭代是Python最強大的功能之一,是訪問集合元素的一種方式。之前介紹的Python容器對象都可以用for循環進行遍歷,代碼如下。生成迭代器>>>forelementin[1,2,3]:...print(element)123>>>forelementin(1,2,3):...print(element)123>>>forkeyin{'one':1,'two':2}:...print(key)onetwo>>>forcharin'123':...print(char)123>>>forlineinopen('../data/myfile.txt'):...print(line)123迭代器(iterator)有兩個基本的函數:iter函數和next函數。如果for循環在容器對象上調用iter函數,那么該函數會返回一個定義next函數的迭代對象,iter函數會在容器對象中逐一訪問元素。當容器對象遍歷完畢,next函數找不到后續元素時,將會引發一個StopIteration異常,終止for循環,代碼如下。生成迭代器>>>L=[1,2,3]>>>it=iter(L)>>>print(it)<list_iteratorat0xa9e0630>>>>print(next(it))1>>>print(next(it))2>>>print(next(it))3>>>print(next(it))StopIteration迭代器是一個可以記錄遍歷位置的對象,從第1個元素被訪問開始,直到所有元素被訪問完結束。迭代器只能往前,不能退后。要將迭代器加入類中,需要定義一個__iter__()方法,它返回一個有next函數的對象。如果類定義了next函數,那么__iter__()方法可以只返回self參數。代碼示例如下。生成迭代器生成迭代器>>>classCat:...def__init__(self,name,age):...=name...self.age=age...=[,self.age]...self.index=-1...defgetName(self):...return...defgetAge(self):...returnself.age...def__iter__(self):...print('名字

年齡')...returnself...defnext(self):...ifself.index==len()-1:...raiseStopIteration...self.index+=1...return[self.index]>>>newcat=Cat('Coffe',3)#創建對象>>>print(newcat.getName())#訪問對象的屬性Coffe>>>iterator=iter(newcat.next,1)#調用迭代函數輸出對象的屬性>>>forinfoiniterator:...print(info)Coffe31返回迭代器目錄生成迭代器2【任務6-3】迭代Car類3生成器是一個返回迭代器的函數,它可以通過常規的def關鍵字來定義,但是不用return語句返回,而是用yield語句一次返回一個結果。一般的函數在生成值后會退出,但生成器在生成值后會自動掛起,暫停執行狀態并保存狀態信息。當函數恢復時,這些狀態信息將再度生效,通過在每個結果之間掛起和繼續它們的狀態自動實現迭代器協議。通過生成斐波那契數列來對比有yield語句和沒有yield語句的情況,進一步了解生成器,代碼如下。1.yield語句1.yield語句>>>deffibonacci(n):#生成器——斐波那契數列...a,b,counter=0,1,0...whileTrue:...ifcounter>n:...return...yielda...a,b=b,a+b...print('%d,%d'%(a,b))...counter+=1>>>f=fibonacci(10)#f是一個迭代器,由生成器返回生成>>>whileTrue:...try:...print(next(f),end='')...except:...break01,111,212,323,535,858,13813,211321,342134,553455,895589,1441.yield語句>>>deffibonacci(n):...a,b,counter=0,1,0...whileTrue:...if(counter>n):...return...#yielda#不執行yield語句...a,b=b,a+b...print('%d,%d'%(a,b))...counter+=1>>>f=fibonacci(10)1,11,22,33,55,88,1313,2121,3434,5555,8989,144列表解析的一般形式如下。2.生成器表達式[exprforiter_variniterableifcond_expr]1,2當迭代iterable里的所有內容時,每一次迭代后,先將iterable里滿足cond_expr條件的內容放到iter_var中,再在表達式expr中應用iter_var的內容,最后用表達式的計算值生成一個列表。例如,生成一個列表以保存50以內的所有奇數。[iforiinrange(50)ifi%2]當序列過長,而每次只需要獲取一個元素時,應當考慮使用生成器表達式生成器表達式是被圓括號括起來的,列表解析式是被方括號括起來的;生成器表達式返回的是一個生成器對象,而列表解析返回的是一個新列表。生成器表達式的一般形式如下。2.生成器表達式(exprforiter_variniterableifcond_expr)使用生成器表達式求出1~10內3或5的倍數,代碼如下。2.生成器表達式>>>g=(iforiinrange(1,10)ifi%3==0ori%5==0)>>>foriing:...print(i)35691返回迭代器目錄生成迭代器2【任務6-3】迭代Car類3【任務6-3】迭代Car類任務分析任務描述對Car類進行迭代,增加品牌(brand)和廢氣渦輪增壓(T)兩個屬性,并輸出所有屬性。(1)在原有Car類上增加品牌(brand)和廢氣渦輪增壓(T)兩個屬性。(2)使用方括號創建列表[brand,wheelnum,color,T],并賦值給變量(info)。(3)為迭代設置初始變量(index)。(4)使用def關鍵字分別定義getBrand、getNewheelnum、getNewcolor、getT函數,用return語句返回對應的屬性值。(5)使用def關鍵字定義__iter__函數,用print函數輸出“品牌車輪數顏色廢氣渦輪增壓”,返回對象位置。(6)使用def關鍵字定義next函數,用if語句進行判斷,返回對應位置的屬性。(7)調用Car類,創建對象newcar,并輸出顏色屬性。(8)訪問對象屬性,調用iter函數,并用print函數輸出結果。類的繼承、重寫、封裝、多態1其他方法目錄繼承父類屬性和方法2【任務6-4】創建Land_Rover子類3繼承(inheritance)是兩個類或多個類之間的父子關系,子類繼承了父類的所有公有數據屬性和方法,并且可以通過編寫子類的代碼擴充子類的功能。繼承實現了數據屬性和方法的重用,減少了代碼的冗余。在程序中,繼承描述的是事物之間的所屬關系。例如,貓和狗都屬于動物,在程序中便可以描述為貓和狗繼承自動物;同理,波斯貓和巴厘貓都繼承自貓,而沙皮狗和斑點狗都繼承自狗,如下圖。1.繼承特定狗種類繼承自狗類,狗類繼承自動物類,狗類編寫了描述所有種類的狗共有的行為和方法,而特定狗種類則增加了狗類特有的行為。繼承也有一定的弊端,例如,某種特定種類的狗不具有絕大部分狗的行為,當程序員沒有厘清類間的關系時,可能會使子類具有不該有的方法。如果繼承鏈太長,那么任何一點小的變化都可能會引起一連串變化。因此,使用繼承時要注意控制繼承鏈的規模。1.繼承在Python中,繼承有以下特點。(1)在繼承中,基類初始化方法__init__()不會被自動調用。如果希望子類調用基類的__init__()方法,那么需要在子類的__init__()方法中顯式調用基類。(2)當調用基類的方法時,需要加上基類的類名前綴,且帶上self參數變量。注意,在類中調用該類定義的方法時是不需要self參數的。(3)Python總是先查找對應類的方法,如果在子類中沒有對應的方法,那么Python才會在繼承鏈的基類中按順序查找。(4)在Python的繼承機制中,子類不能訪問基類的私有成員。1.繼承1.繼承利用繼承機制修改Cat類的代碼,添加繼承方法,代碼如下。>>>classCat:...def__init__(self):...='貓'...self.age=4...=[,self.age]...self.index=-1...defrun(self):...returnf"{}--在跑"...defgetName(self):...return...defgetAge(self):...returnself.age...def__iter__(self):...print('名字

年齡')...returnself...defnext(self):...ifself.index==len()-1:...raiseStopIteration...self.index+=1...return[self.index]1.繼承>>>classBosi(Cat):...defsetName(self,newName):...=newName...defeat(self):...returnf"{}--在吃">>>bs=Bosi()#創建對象>>>print('bs的名字為:',)#繼承父類的屬性和方法bs的名字為:貓>>>print('bs的年齡為:',bs.age)bs的年齡為:4>>>print(bs.run())貓--在跑>>>bs.setName('波斯貓')#子類的屬性和方法>>>print(bs.eat())波斯貓--在吃>>>iterator=iter(bs.next,1)#迭代輸出父類的屬性>>>forinfoiniterator:...print(info)貓4上述代碼定義了Bosi類的父類Cat,將貓共有的屬性和方法都放到父類中,子類僅需要向父類傳輸數據屬性。這樣可以很輕松地定義其他基于Cat類的子類。在Bosi類的__init__()方法中顯式調用了Cat類的__init__()方法,并向父類傳輸數據,注意這里需要加self參數。因為在繼承中子類不能繼承父類的私有屬性,所以不用擔心父類和子類會出現因繼承造成的重名情況。子類不能繼承父類的私有屬性的代碼如下。1.繼承1.繼承>>>classanimal:...def__init__(self,age):...self.__age=age...defprint2(self):...print(self.__age)>>>classdog(animal):...def__init__(self,age):...animal.__init__(self,age)...defprint2(self):...print(self.__age)>>>a_animal=animal(10)>>>a_animal.print2()10>>>a_dog=dog(10)>>>a_dog.print2()#程序報錯AttributeError:'dog'objecthasnoattribute'_

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論