生成器 (generator)
-
概念
- 在Python中, 一邊循環一邊計算的機制, 稱為生成器: generator 創建生成器: G = ( x*2 for x in range(5)) 可以通過 next(生成器) 函數獲得生成器的下一個返回值 沒有更多的元素時, 拋出 StopIteration 的異常 生成器也可以使for 循環,因為生成器也是可迭代對象
-
生成器的生成方式1:
list2 = [x for x in range(10)] print(type(list2)) # 得到一個生成器對象 g = (x*2 for x in range(10)) print(type(g)) # 打印生成器生成的第一個數字 print(next(g)) print(next(g)) print(next(g)) 一共10個數字,打印超出報StopIteration異常
- 應用: 求斐波那契數列的第n個數
def fibo(n): a,b=1,1 i = 3 while i <= n: if i == 1 or i == 2: return 1 else: a,b = b,a+b i += 1 else: print(b)
-
生成器的生成方式2(包含yield關鍵字的函數):
def getNum(): for i in range(10): yield i
-
生成器中元素的訪問方式:
- 1.next()
- 2.g.__next()
- 3.g.send('發送的參數')
def gen(): print('a') count = yield 1 print ('--->',count) print ('b') yield 2 #注意打印結果 g = gen() next(g) g.send('123') next(g)
-
其他使用場景:(攜程,實現兩個任務的交替調用)
def save(): while True: yield print ('save') def draw(): while True: yield print ('draw') g1 = save() g2 = draw() while True: next(g1) next(g2)
迭代器 (Iterator)
- 概念: 擁有__iter__方法和__next__方法的對象就是迭代器
- 迭代
- 迭代是訪問集合元素的一種方式,可以將某個數據集內的數據“一個挨着一個的取出來”,就叫做迭代
- 可迭代協議
- 協議就是互相規定好的。可迭代協議的定義非常簡單,就是內部實現了 __iter__方法。
- 迭代器協議
- 迭代器協議:必須擁有__iter__方法和__next__方法
- 可以通過dir(對象)查看是否實現了__iter__,__next__等方法來判斷對象是否為迭代器
- 也可以使用 isinstance(Iterator)來判斷
- 練習:
- 查看__iter__()的返回值
- 查看__iter__()包含的方法
- 分別查看迭代器與列表的方法
- 迭代
- for循環的本質
- 通過__iter__()獲取該對象的一個迭代器對象
- 通過__next__()函數,依次獲取下一個元素
閉包
- 什么是閉包?
- 在 python 中創建一個閉包一般有 3 個要求:
- 1.閉包函數必須有內嵌函數。
- 2.內嵌函數必須要引用外層函數的變量。
- 3.閉包函數返回內嵌函數的地址(函數名稱)
- 在 python 中創建一個閉包一般有 3 個要求:
- 創建一個閉包函數:
def funcOut(): name = 'Jery' def funcIn(): print(name) return funcIn f = funcOut() f()
- 判斷是否為閉包函數
def funcOut(): name = 'abc' def funcIn(): print(name) pass #如果打印None,則不是閉包函數 print(funcIn.__closure__) return funcIn f=funcOut() f()
裝飾器
- 裝飾器的本質:(閉包函數)
- 裝飾器的作用:
- 在不修改原函數及其調用方式的情況下對原函數功能進行擴展
- 裝飾器的使用:
- 需求:為現有功能fun1增加日志功能
- 傳統方案解決
- 使用閉包解決
def outfunc(func): def infunc(): writeLog() func() return infunc def fun1(): print("使用功能1") def fun2(): print("使用功能2") # 注意名字的問題,需要分析 fun1 = outfunc(fun1) # 裝飾器(閉包) fun1() 使用裝飾器(語法糖)解決 def outfunc(func): def infunc(): writeLog() func() return infunc @outfunc def fun1(): print("使用功能1") @outfunc def fun2(): print("使用功能2") fun1() fun2()
- 多個裝飾器的使用
def add1(fc): print("add1正在裝飾") def wrapped(): return "《"+fc()+"》" return wrapped def add2(fc): print("add2正在裝飾") def wrapped(): return '*'+fc()+'*' return wrapped #看到這個,開始進行裝飾,而不是等到調用時 @add1 @add2 def test1(): return '金陵十三釵' print(test1())
- 對有參數的函數進行裝飾
def func(fn): print("func") def func_in(aa, bb): print("func_in1") fn(aa,bb) print("func_in2") return func_in @func def test(a, b): print("a=%d,b=%d" % (a, b)) # 裝飾器裝飾之后,這不是直接調用test方法,而是調用func_in方法 test(1,2)
- 通用裝飾器的使用
def func(fn): # 需要有參數,*args,**kwargs def func_in(*args,**kwargs): print("記錄日志") print('訪問方法:'+fn.__name__) # 需要有參數,*args,**kwargs xx = fn(*args,**kwargs) # 需要有返回值 return xx return func_in
# 待裝飾函數:無參數,無返回值
@func def test1(): print("test1") test1() @func def test2(): return "Hello" print(test2()) @func def test3(a): print('a=%d'%a) test3(1)
類方法靜態方法
- 靜態方法:
- 1.格式:在方法上面添加 @staticmethod
- 2.參數:靜態方法可以有參數也可以無參數
- 3.應用場景:一般用於和類對象以及實例對象無關的代碼。
- 4.使用方式: 類名.類方法名(或者對象名.類方法名)
- 使用示例: 比如:學生管理系統的展示主菜單
- 類方法:
- 無需實例化,可以通過類直接調用的方法,但是方法的第一個參數接收的一定是類本身
- 1.在方法上面添加@classmethod
- 2.方法的參數為 cls 也可以是其他名稱,但是一般默認為 cls
- 3.cls 指向 類對象(也就是 Goods)
- 4.應用場景:當一個方法中只涉及到靜態屬性的時候可以使用類方法(類方法用來修改類屬 性)。
- 5.使用 可以是 對象名.類方法名。或者是 類名.類方法名
- 使用示例:
- 修改所有商品的折扣
class Goods(): discount = 1 def __init__(self,price,name): self.name = name self.price = price def price_discount(self): return self.price * Goods.discount @classmethod def change_discount(cls,new_discount): cls.discount = new_discount