一、迭代器
1.可迭代對象
可迭代對象【實(shí)體】:可以直接作用于for循環(huán)的實(shí)體【Iterable】
可以直接作用于for循環(huán)的數(shù)據(jù)類型:
? a.list,tuple,dict,set,string
? b.generator【() 和yield】
isinstance:判斷一個實(shí)體是否是可迭代的對象
代碼演示:
#一贸弥、可迭代對象 #1.導(dǎo)入 from collections import Iterable #2.使用isinstance(數(shù)據(jù)迈螟,Iterable) print(isinstance([],Iterable)) print(isinstance((),Iterable)) print(isinstance({},Iterable)) print(isinstance((x for x in range(10)),Iterable)) print(isinstance("hello",Iterable)) print(isinstance(10,Iterable)) #False print(isinstance(True,Iterable)) #False print("****88")
2.迭代器
不但可以作用于for循環(huán),還可以被next函數(shù)遍歷【不斷調(diào)用并返回一個元素猬膨,直到最后一個元素被遍歷完成角撞,則出現(xiàn)StopIteration】
目前為止,只有生成器才是迭代器【Iterator】
結(jié)論:迭代器肯定是可迭代對象勃痴,但是谒所,可迭代對象不一定是迭代器
isinstance:判斷一個實(shí)體是否是迭代器
代碼演示:
#二、迭代器 from collections import Iterator print(isinstance([],Iterator)) print(isinstance((),Iterator)) print(isinstance({},Iterator)) print(isinstance("hello",Iterator)) print(isinstance((x for x in range(10)),Iterator)) #True print("****88")
3.可迭代對象和迭代器之間的轉(zhuǎn)換
可以將可迭代對象轉(zhuǎn)換為迭代器:iter()
代碼演示:
#三沛申、雖然list劣领、tuple、dict铁材、set尖淘、string都不是迭代器 #iter():將list、tuple著觉、dict村生、set、string的 Iterable轉(zhuǎn)換為Iterator print(isinstance(iter([]),Iterator)) print(isinstance(iter(()),Iterator)) print(isinstance(iter({}),Iterator)) print(isinstance(iter("hello"),Iterator))
總結(jié):
? a.凡是可以作用于for循環(huán)的對象都是Iterable類型
? b.凡是可以作用于next函數(shù)的對象都是Iterator類型
? c.list/tuple/dict/set/string都不是Iterator饼丘,可以通過iter()獲得一個Iterator對象
【面試題】
區(qū)分可迭代對象和迭代器
三趁桃、裝飾器
1.案例
代碼演示:
def test(): print("拼搏到無能為力,堅持到感動自己") f = test() #變量可以指向指向函數(shù)肄鸽,函數(shù)名也是一個變量卫病,所以變量可以當(dāng)做函數(shù)調(diào)用 f() #思考問題:test增加功能,但是不能修改test函數(shù)內(nèi)部----->裝飾器
在代碼運(yùn)行期間典徘,可以動態(tài)增加函數(shù)功能的方式忽肛,被稱為裝飾器【Decorator】
也就是說,在不修改原函數(shù)的基礎(chǔ)上烂斋,給原函數(shù)增加功能
好處:在團(tuán)隊開發(fā)中屹逛,如果兩個或者兩個以上的程序員會用到相同的功能,但是功能又有細(xì)微的差別汛骂,采用裝飾器:相互不影響罕模,代碼簡化
2.使用
2.1簡單裝飾器
代碼演示:
#1.簡單的裝飾器 def test(): print("拼搏到無能為力,堅持到感動自己") #a.書寫閉包 #b.給外部函數(shù)設(shè)置參數(shù),fun表示的是原函數(shù) def outer(fun): def inner(): # d.給原函數(shù)增加功能 print("hello") #c.調(diào)用原函數(shù) fun() return inner #e.使用閉包 f = outer(test) #f = inner f() #inner() #注意:增加的功能可以寫在原函數(shù)調(diào)用的前面或者后面 #注意:outer函數(shù)就被稱為裝飾器 #練習(xí):給下面的函數(shù)添加功能帘瞭,打印九九乘法表 def show(): for i in range(10): print(i) def outer1(fun): def inner1(): fun() for i in range(1,10): for j in range(1,i + 1): print("%dx%d=%d"%(j,i,i * j),end=" ") print("") return inner1 f1 = outer1(show) f1()
2.2有參數(shù)的裝飾器
代碼演示:
#2.原函數(shù)有參數(shù)的裝飾器 def getAge(age): print(age) getAge(10) getAge(-5) print("************") #需求:在不修改原函數(shù)的基礎(chǔ)上淑掌,進(jìn)行數(shù)據(jù)的過濾:當(dāng)用戶輸入age為負(fù)數(shù)的時候,則置為0 def wrapper(fun): #注意:當(dāng)原函數(shù)有參數(shù)蝶念,裝飾器的作用是為了操作原函數(shù)中的參數(shù)抛腕,給inner設(shè)置參數(shù) def inner(num): #增加新功能:過濾負(fù)數(shù) if num < 0: num = 0 #調(diào)用原函數(shù) fun(num) #age = num return inner f = wrapper(getAge) f(10) #num = 10 f(-5)
2.3系統(tǒng)的簡寫
代碼演示:
#3.簡化demo2中的操作:@裝飾器的名稱 應(yīng)用到原函數(shù)中 #需求:在不修改原函數(shù)的基礎(chǔ)上芋绸,進(jìn)行數(shù)據(jù)的過濾:當(dāng)用戶輸入age為負(fù)數(shù)的時候,則置為0 def wrapper(fun): #注意:當(dāng)原函數(shù)有參數(shù)担敌,裝飾器的作用是為了操作原函數(shù)中的參數(shù)摔敛,給inner設(shè)置參數(shù) def inner(num): #增加新功能:過濾負(fù)數(shù) if num < 0: num = 0 #調(diào)用原函數(shù) fun(num) #age = num return inner #將wrapper裝飾器應(yīng)用在了getAge函數(shù)上, @wrapper def getAge(age): print(age) getAge(10) getAge(-5) """ @wrapper 等價于 f = wrapper(getAge) f(10) #num = 10 #注意;當(dāng)使用@的時候全封,在同一個文件中马昙,裝飾器必須出現(xiàn)的原函數(shù)的前面 """
2.4不定長參數(shù)的裝飾器
代碼演示:
#4.不定長參數(shù)的裝飾器 #應(yīng)用場景:當(dāng)同一個裝飾器作用于不同函數(shù)的時候,這些函數(shù)的參數(shù)的個數(shù)是不相同的 def wrapper(fun): def inner(*args): print("hello") fun(*args) #a = args[0] b = args[1] return inner @wrapper def fun1(a,b): print(a + b) @wrapper def fun2(a,b,c,d): print(a,b,c,d) fun1(10,20) #args = (10,20) fun2(1,2,3,4)
2.5多個裝飾器作用于同一個函數(shù)
代碼演示:
#5.將多個裝飾器應(yīng)用到同一個函數(shù)上 def wrapper1(fun): def inner1(): print("1~~~~") fun() return inner1 def wrapper2(fun): def inner2(): print("2~~~~") fun() return inner2 @wrapper1 @wrapper2 def show(): print("hello") show() """ 1~~~~ 2~~~~ hello """ #結(jié)論:多個裝飾器作用于同一個函數(shù)的時候刹悴,從第一個裝飾器開始行楞,從上往下依次執(zhí)行,但是土匀,原函數(shù)只會被執(zhí)行一次
四子房、函數(shù)遞歸【掌握】
1.概念
遞歸函數(shù):一個會調(diào)用自身的函數(shù)【在一個函數(shù)的內(nèi)部,自己調(diào)用自己】
遞歸調(diào)用
遞歸中包含了一種隱式的循環(huán)就轧,他會重復(fù)指定某段代碼【函數(shù)體】池颈,但這種循環(huán)不需要條件控制
使用遞歸解決問題思路:
? a.找到一個臨界條件【臨界值】
? b.找到相鄰兩次循環(huán)之間的關(guān)系
? c.一般情況下,會找到一個規(guī)律【公式】
2.使用
代碼演示:
#案例一 """ 1 2 3 4 5 6 7 8 9 10 11.钓丰。躯砰。。 斐波那契數(shù)列:1,1,2,3,5,8,13,21,34,55,89..... 解決問題:報一個數(shù)携丁,輸出數(shù)列中對應(yīng)的數(shù) 規(guī)律: a.第一個位置和第二個位置上數(shù)是固定的琢歇,都是1 b.第n個位置上的數(shù):第 n - 1 的數(shù) + 第 n - 2 的數(shù) r1 = func1(1) ------>1 r2 = func1(2) ------>1 r3 = fun1(3) ------>func1(1) + func1(2)----->1 + 1 = 2 r4 = fun1(4)------->fun1(3) + fun1(2) ----->func1(1) + func1(2) + fun1(2) ---->1 + 1 + 1 = 3 r5 = fun1(5) ----->fun1(4) + fun1(3) ----->fun1(3) + fun1(2) + func1(1) + func1(2)--->func1(1) + func1(2) ++ fun1(2) + func1(1) + func1(2)--->5 ..... rn = fun1(n) ----->fun1(n- 1) + fun1(n - 2) """ def func1(num): #臨界值 if num == 1 or num == 2: return 1 else: #print("~~~~",num) result = func1(num- 1) + func1(num - 2) #result = func1(1) + func1(2) --->1 + 1 =2 return result print(func1(10)) #練習(xí);使用遞歸計算1~某個數(shù)之間的和 """ add(1) = 1 :臨界值 add(2) = add(1) + 2 add(3) = add(2) + 3 ---->add(1) + 2 + 3 = 1 + 2 + 3 add(4) = add(3) + 4---->add(2) + 3 + 4 ---->add(1) + 2 + 3 + 4---->1 + 2 + 3 + 4 .... add(n) = add(n - 1) + n """ def add(num): """ n = 1 sum = 0 while n <= 100: sum += n n += 1 return sum sum1 = 0 for i in range(1,num + 1): sum1 += i return sum1 """ #使用遞歸實(shí)現(xiàn) if num == 1: return 1 else: return add(num - 1) + num print(add(100))
注意:以后在實(shí)際項目中盡量少用遞歸,如果隱式循環(huán)的次數(shù)太多梦鉴,會導(dǎo)致內(nèi)存泄漏【棧溢出】
優(yōu)點(diǎn):簡化代碼李茫,邏輯清晰
五、棧和隊列【了解】
用于存儲數(shù)據(jù)的線性表
棧:在表的一端進(jìn)行插入和刪除
隊列:在表的一端進(jìn)行插入肥橙,在表的另一端進(jìn)行數(shù)據(jù)的刪除
1.棧
Stack
開口向上的容器:先進(jìn)后出魄宏,后進(jìn)先出
代碼演示:
#list的底層維護(hù)了一個棧的線性表 myStack = [] #插入數(shù)據(jù) #數(shù)據(jù)入棧【壓棿娣ぃ】 myStack.append(1) print(myStack) myStack.append(2) print(myStack) myStack.append(3) print(myStack) myStack.append(4) print(myStack) #[1,2,3,4] #出棧 myStack.pop() print(myStack) myStack.pop() print(myStack) myStack.pop() print(myStack) myStack.pop() print(myStack)
2.隊列
queue
水平放置的水管:先進(jìn)先出宠互,后進(jìn)后出
代碼演示:
import collections #數(shù)據(jù)結(jié)構(gòu)的集合 queue = collections.deque([1,2,3,4]) print(queue) #入隊【存儲數(shù)據(jù)】 queue.append(5) print(queue) queue.append(6) print(queue) #出隊【獲取數(shù)據(jù)】 queue.popleft() print(queue) queue.popleft() print(queue) queue.popleft() print(queue)