python遞歸 及 面向對象初識及編程思想
一、遞歸
1、定義:
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
(1)遞歸就是在過程或函數裏調用自身;
(2)在使用遞歸策略時,必須有一個明確的遞歸結束條件,稱為遞歸出口。
1 def age(n): 2 if n ==1: #條件判定 3 return 10 #返回一個結果 4 else: 5 return age(n-1)+2 #重復調用函數本身,系統會將運算的結果存放到棧,然後再依次的進行取值調用。 6 print(age(5)) #打印結果
執行結果:18
2、優缺點:
遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。
遞歸的缺點:遞歸算法解題的運行效率較低。在遞歸調用的過程當中系統為每一層的返回點、局部量等開辟了棧來存儲。遞歸次數過多容易造成棧溢出等。
def func(): print("*******") func() func() #執行結果 [Previous line repeated 993 more times] ******* File "F:/py_fullstack_s4/day26/遞歸.py", line 8, in func ******* print("*******") ******* RecursionError: maximum recursion depth exceeded while calling a Python object
3、遞歸編程的註意點:
1. 必須有一個明確的結束條件。
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少。
3.遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)。
4、此處引出一個新的知識點:二分法
二分法,是一種快速查找的方法,時間復雜度低,邏輯簡單易懂,總的來說就是不斷的除以2除以2...
他主要應用於有序序列中,原理是每次查找都將原序列折半,逐漸縮小查找範圍的一種算法。應用於遞歸,循環之中,直到找到結果。
#運用 遞歸 和 二分法 的運算方式,查找列表中的某個值 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] num = int(input("please input your want to find number:")) def search(num,data): if len(data) > 1: #排除列表分割,僅剩一個元素的情況 #二分法# a = int(len(data)//2) #將計算列表的長度,除以2 取整數 mid_value = data[a] #取當前中間的值 if num > mid_value: #要找的值 大於 中間的值 data = data[a:] #將原列表從中間值往後,取出來,構建一個新列表 search(num,data) #遞歸判斷 elif num < mid_value: #要找的值 小於 中間的值 data = data[:a] #將原列表開始到中間值,取出來,構建一個新列表 search(num,data) #遞歸判斷 else: #正好是這個值 print("find it!!",num) return #打印 else: #判斷列表分割,僅剩一個元素的情況 if data[0] == num: print(‘find it!! %s‘%data[0]) else: #列表中沒有這個值 print(‘not this num %s‘%num) search(num,data) #執行結果: please input your want to find number:18 find it!! 18
二、函數式編程介紹
1、用def模仿數學中函數的方式,傳一個值,就得一個結果。不會修改外部的狀態。
2、代碼非常的精簡,直接導致可讀性非常差。
三、面向對象的程序設計
1、前提鋪墊:
python中一切皆為對象,python 3統一了類與類型的概念,類型即是類。例如:int,str,list,等等……
編程語言中,是先有了類,然後再產生一個個對象。而現實生活中正好相反。
明確一點:面向對象編程是一種編程方式,此編程方式的功能需要使用 “類” 和 “對象” 來實現,所以,面向對象編程其實就是對 “類” 和 “對象” 的使用。
類就是一個模板,模板裏可以包含創建多個函數,函數裏實現自定義的功能
對象則是根據模板創建的實例,通過實例(對象)可以執行類中定義的函數
2、語法:
1)創建類:class是關鍵字,表示類 class *** #創建類
2)創建對象:類名稱後加括號 將結果賦給一個變量 即可 x = ***() #創建對象
1 class hello: #任意定義一個類 2 camp = ‘hello world‘ 3 def f(self): 4 print("f") 5 h = hello() # 類實例化 6 print(h) #打印 7 8 #執行結果: 9 10 <__main__.hello object at 0x00000000026C9630>
3、類與對象
1)什麽是對象:
以遊戲舉例:英雄聯盟,每個玩家選一個英雄,每個英雄都有自己的特征和和技能,特征即數據屬性,技能即方法屬性,特征與技能的結合體就一個對象。
2)什麽是類:
從一組對象中提取對象共同的 特征,技能,構成一個類。類也是特征與技能的結合體,特征即數據並且是所有對象共享的數據,技能即函數屬性並且是所有對象共享的函數屬性。
①優點:解決了程序的擴展性,對某個對象進行修改,會立刻反映到整個體系中
②缺點:可控性差,無法預測最終的結果。
面向對象的程序設計並不是程序全部。對於軟件質量來說,面向對象的程序設計只是用來解決擴展性的問題。
def 或是 class 都是在定義一個函數名。class 定義 類 camp 陣營 attack(self) 技能 nickname昵稱 init 開始,初始
3)如何使用類:
一、實例化
類的實例化就會產生一個實例(對象)。 可以理解為類加()把虛擬的東西實例化,得到具體存在的值,叫做類的實例化。
class Garen: #定義一個類 camp = ‘Demacia‘ def attack(self): print(‘attack‘) g1 = Garen() #類的實例化,產生一個對象,可以調用類內包括的所有特征(共性)。 print(g1) #打印 #執行結果: <__main__.Garen object at 0x00000000028C9CC0>
二、類通過.(點)的方式引用特征(類的變量)和技能(類的函數(類內部還是定義的函數,調用的話還是需要傳入參數))
class Garen: camp=‘Demacia‘ def attack(self): print(‘attack‘) print(Garen.camp) #查看camp print(Garen.attack) #打印數據類型 Garen.attack(‘nihao‘) #由於是調用有參函數,需要傳值 #執行結果: Demacia <function Garen.attack at 0x000000000229C950> attack
2、對象之間也有不同,及除了同性也有特性。例如昵稱!
class Garen: camp=‘Demacia‘ def __init__(self,nickname): self.nick=nickname #給實例自己定義一個別名,由外部傳入 #g1.nick = ‘草叢倫‘ def attack(self,enemy): # print(‘---------->‘,self.nick) #g1.nick print(‘%s attack %s‘ %(self.nick,enemy)) g1=Garen(‘草叢倫‘) #類實例化,類Garen觸發調用_init_ #Garen._init_(self,‘NB‘) g2=Garen(‘劉下‘) print(g1.nick) g1.attack(‘alex‘) #執行結果: 草叢倫 草叢倫 attack alex
self 指自己。
註意:類的實例化就會自動觸發類內_init_函數的執行。
3、怎麽調用類的特征與技能
註意:類與對象之間的綁定方法。調用綁定方法,python 會自動傳值,會將調用者本身當作參數傳給self,第一值。
print(gi.attack) #調用綁定方法,類綁定給g1
print(Garen.attack) #函數
class Garen: camp=‘Demacia‘ def __init__(self,nickname): self.nick=nickname #給實例自己定義一個別名,由外部傳入 #g1.nick = ‘草叢倫‘ def attack(self,enemy): # print(‘---------->‘,self.nick) #g1.nick print(‘%s attack %s‘ %(self.nick,enemy)) g1=Garen(‘草叢倫‘) #類實例化,類Garen觸發調用_init_ #Garen._init_(self,‘NB‘) g2=Garen(‘劉下‘) print(g1.nick) #昵稱 print(g1.camp) #陣營 print(g1.attack) #打印 查看綁定方法 print(Garen.attack) # 打印 函數 #執行結果: 草叢倫 Demacia <bound method Garen.attack of <__main__.Garen object at 0x0000000002299D68>> <function Garen.attack at 0x000000000229C9D8>
Garen.attack(參數)# 調用的是函數,需要傳參
g1.attack(‘alex‘) #self = g1;enemy = ‘alex‘若是函數有多個值,就在賦值的時候,傳入其他的參數。
print(g1.nick)
只要是對象觸發的,調用的時候就會自動給調用的函數傳值,將自身傳到第一個參數self。若是函數有多個值,就在賦值的時候,對應的傳入其他的參數。
class Garen: camp=‘Demacia‘ def __init__(self,nickname): self.nick=nickname #給實例自己定義一個別名,由外部傳入 #g1.nick = ‘草叢倫‘ def attack(self,enemy): # print(‘---------->‘,self.nick) #g1.nick print(‘%s attack %s‘ %(self.nick,enemy)) g1=Garen(‘草叢倫‘) #類實例化,類Garen觸發調用_init_ #Garen._init_(self,‘NB‘) g2=Garen(‘劉下‘) print(g2.nick) print(g2.camp) #執行結果: 劉下 Demacia
三、總結:
1、類:一:實例化,二:引用名字(類名.變量名,類名.函數名) 得到一個內存地址,加()就能運行。
2、實例(對象):引用名字(實例名.類的變量,實例名.綁定方法,實例名.實例自己的變量名)
3、類:
優點:解決了程序的擴展性,對某個對象進行修改,會立刻反映到整個體系中
缺點:可控性差,無法預測最終的結果。
面向對象的程序設計並不是全部。對於軟件質量來說,面向對象的程序設計只是用來解決擴展性的問題。
在python中,用變量表示特征,用函數表示方法,因而類是變量與函數的結合體,對象是變量與方法(指向類的函數)的結合體
4、類屬性:特征(變量)和方法(函數)
5、類有兩種方法:1.類的實例化;2.屬性引用
1.實例化:
類名加括號就是實例化,會自動觸發__init__函數的運行,可以用它來為每個實例定制自己的特征
2.屬性引用:
類名.方法
6、對象也稱為實例
對象的屬性:對象本身就自有特征(變量)
對象的只有一種用法:屬性引用
7、類的名稱空間和對象的名稱空間
創建一個類,就會創建一個類的名稱空間,存放類中定義的屬性:特征(數據)和方法(函數)
創建一個對象,及類的實例化,就會創建一個類的名稱空間,存放對象的屬性。
註意:對象就是類的實例化,類完成實例化的操作就已經將類的方法綁定到對象上,對象調用方法會現在自己的名稱空間去找,找不到會去類的名稱空間去找,再找不到會拋異常。它不會去找全局的定義。
查看類的名稱空間 類名._dict_
查看對象的名稱空間 對象名._dict_
綁定方法的核心在於‘綁定’,唯一綁定到一個確定的對象
可以調用:查
print(Garen.camp) #查
可以更改:改
Garen.camp=‘aaaaaa‘ #改
print(Garen.camp)
可以刪除: 刪
del Garen.camp #刪除
print(Garen.camp)
可以添加: 增
Garen.x=1 #增加特征
print(Garen.x)
關於對象(實例)
可以調用: 查
g1=Garen(‘alex‘)
print(g1.nick) #查
可以更改: 改
g1.nick=‘asb‘ #改
print(g1.nick)
可以刪除: 刪
del g1.nick
print(g1.nick) #刪
可以增加: 增
g1.sex=‘female‘
print(g1.sex) #增加
四、面向對象的軟件開發:
分為五部:
1、面向對象分析(object oriented analysis,OOA):
產品經理調研市場,考察,明確軟件的用途和應用場景。
2、面向對象設計(object oriented design,OOD):
根據需求,對每一部分進行具體的設計,例如:類的設計
3、面向對象編程(object oriented programming,OOP):
將設計編程成代碼
4、面向對象測試(object oriented test,OOT):
對寫好的代碼進行測試,發現錯誤並改正。面向對象的測試是用面向對象的方法進行測試,以類為測試的基本單元。
5、面向對象維護(object oriented soft maintenance,OOSM):
解決用戶使用產品過程中出現的問題,或是增加新的功能。
面向對象編程思想:
1、設計的時候,一定要明確應用場景
2、由對象分析定義類的時候,找不到共同特征和技能不用強求
python遞歸 及 面向對象初識及編程思想