4.python迭代器生成器裝飾器

基本概念

1.容器(container)

容器是一種把多個元素組織在一塊兒的數據結構,容器中的元素能夠逐個地迭代獲取,能夠用in, not in關鍵字判斷元素是否包含在容器中。一般這類數據結構把全部的元素存儲在內存中(也有一些特例,並非全部的元素都放在內存,好比迭代器和生成器對象)在Python中,常見的容器對象有:數據結構

  • list, deque, ….
  • set, frozensets, ….
  • dict, defaultdict, OrderedDict, Counter, ….
  • tuple, namedtuple, …
  • str

容器比較容易理解,由於你就能夠把它看做是一個盒子、一棟房子、一個櫃子,裏面能夠塞任何東西。從技術角度來講,當它能夠用來詢問某個元素是否包含在其中時,那麼這個對象就能夠認爲是一個容器,好比 list,set,tuples都是容器對象.app

2.可迭代對象(iterable)

凡是能夠返回一個迭代器的對象均可稱之爲可迭代對象函數

3.迭代器(iterator)

那麼什麼迭代器呢?它是一個帶狀態的對象,他能在你調用next()方法的時候返回容器中的下一個值,任何實現了__iter____next__()方法的對象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一個值,若是容器中沒有更多元素了,則拋出StopIteration異常,至於它們究竟是如何實現的這並不重要。post

生成器(generator)

一個包含了yield關鍵字的函數就是一個生成器,該函數也叫生成器函數。當生成器函數被調用時,在函數體中的代碼不會被執行,而會返回一個迭代器。每次請求一個值,就會執行生成器中代碼,直到遇到一個yield表達式或return語句。yield表達式表示要生成一個值,return語句表示要中止生成器。換句話說,生成器是由兩部分組成,生成器的函數和生成器的迭代器。生成器的函數是用def語句定義的,包含yield部分;生成器的迭代器是這個函數返回的部分。兩者合起來叫作生成器。this

 迭代器與生成器

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.更復雜的裝飾器

對這兩個函數分別統計運行時間,再加一層函數來接受參數,根據嵌套函數的概念,要想執行內函數,就要先執行外函數,才能調用到內函數spa

複製代碼
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()
複製代碼
相關文章
相關標籤/搜索