4.python迭代器生成器裝飾器
阿新 • • 發佈:2018-12-30
基本概念
1.容器(container)
容器是一種把多個元素組織在一起的資料結構,容器中的元素可以逐個地迭代獲取,可以用in
, not in
關鍵字判斷元素是否包含在容器中。通常這類資料結構把所有的元素儲存在記憶體中(也有一些特例,並不是所有的元素都放在記憶體,比如迭代器和生成器物件)在Python中,常見的容器物件有:
- list, deque, ….
- set, frozensets, ….
- dict, defaultdict, OrderedDict, Counter, ….
- tuple, namedtuple, …
- str
容器比較容易理解,因為你就可以把它看作是一個盒子、一棟房子、一個櫃子,裡面可以塞任何東西。從技術角度來說,當它可以用來詢問某個元素是否包含在其中時,那麼這個物件就可以認為是一個容器,比如 list,set,tuples都是容器物件.
2.可迭代物件(iterable)
凡是可以返回一個迭代器的物件都可稱之為可迭代物件
3.迭代器(iterator)
那麼什麼迭代器呢?它是一個帶狀態的物件,他能在你呼叫next()
方法的時候返回容器中的下一個值,任何實現了__iter__
和__next__()
方法的物件都是迭代器,__iter__
返回迭代器自身,__next__
返回容器中的下一個值,如果容器中沒有更多元素了,則丟擲StopIteration異常,至於它們到底是如何實現的這並不重要。
生成器(generator)
一個包含了yield關鍵字的函式就是一個生成器,該函式也叫生成器函式。當生成器函式被呼叫時,在函式體中的程式碼不會被執行,而會返回一個迭代器。每次請求一個值,就會執行生成器中程式碼,直到遇到一個yield表示式或return語句。yield表示式表示要生成一個值,return語句表示要停止生成器。換句話說,生成器是由兩部分組成,生成器的函式和生成器的迭代器。生成器的函式是用def語句定義的,包含yield部分;生成器的迭代器是這個函式返回的部分。二者合起來叫做生成器。
迭代器與生成器
1.迭代器使用舉例:
city = ['beijing','shanghai','tinajin','chongqin'] it = iter(city) print(type(it)) #方法一:使用next方法來使用迭代器 print(it.__next__()) print(it.__next__()) 方法二:使用for迴圈來使用迭代器 for x in it: print(x)
2 用生成器函式完成與counter類似功能
def generator(low,high): while low <= high:yield low low += 1 for i in generator(1,10): print(i,end='') 結果:12345678910
3. 生成器產生無限多的值
def generator(start = 0): while True: yield start start += 1 for number in generator(4): print(number,end='') if number > 20: break
4. 列表生成器
a = [i*2 for i in range(1,10)] print(a)
結果: [2, 4, 6, 8, 10, 12, 14, 16, 18]
裝飾器
要求: 不能修改被裝飾的函式的原始碼 不能修改被裝飾的函式的呼叫方式 滿足上面的兩種情況下給程式增添功能 組成: < 函式+實參高階函式+返回值高階函式+巢狀函式+語法糖 = 裝飾器 >
1.簡單裝飾器
1 import time 2 def timer(func): 3 def wrapper(): 4 start_time = time.time() 5 func() 6 stop_time = time.time() 7 print("run time %s"%(stop_time-start_time)) 8 return wrapper 9 @timer #語法糖 test=timer(test) 10 def test(): 11 time.sleep(3) 12 print("in the test") 13 test() 14 15 結果: 16 in the test 17 run time 3.000171661376953。
1.test表示的是函式的記憶體地址 2.test()就是呼叫對在test這個地址的內容,即函式 高階函式: 1.把一個函式名當作實參傳給另外一個函式(“實參高階函式”) 2.返回值中包含函式名(“返回值高階函式”) 這裡面所說的函式名,實際上就是函式的地址,把函式名當做實參,那麼也就是說可以把函式傳遞到另一個函式,然後在另一個函式裡面做一些操作。 巢狀函式: 巢狀函式指的是在函式內部定義一個函式,而不是呼叫 函式只能呼叫和它同級別以及上級的變數或函式。也就是說:裡面的能呼叫和它縮排一樣的和他外部的,而內部的是無法呼叫的。 把test作為引數傳遞給了timer(),此時,在timer()內部,func = test,接下來,定義了一個wrapper()函式,但並未呼叫,只是在記憶體中儲存了,並且
標籤為wrapper。在timer()函式的最後返回wrapper()的地址wrapper。然後再把wrapper賦值給了test,那麼此時test已經不是原來的test了,也就是test原來的那些函式體的標籤換掉了,換成了wrapper
2.裝飾有參函式
import time def timer(func): def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print(stop_time-start_time) return deco @timer def test(parameter): time.sleep(3) print("test is running") test("新增引數")
3.更復雜的裝飾器
對這兩個函式分別統計執行時間,再加一層函式來接受引數,根據巢狀函式的概念,要想執行內函式,就要先執行外函式,才能呼叫到內函式
import time def timer(parameter): def outer_wrapper(func): def wrapper(*args, **kwargs): if parameter == 'task1': start = time.time() func(*args, **kwargs) stop = time.time() print("the task1 run time is :", stop - start) elif parameter == 'task2': start = time.time() func(*args, **kwargs) stop = time.time() print("the task2 run time is :", stop - start) return wrapper return outer_wrapper @timer(parameter='task1') def task1(): time.sleep(2) print("in the task1") @timer(parameter='task2') def task2(): time.sleep(2) print("in the task2") task1() task2()