天天看點

【Python系列】為啥老問裝飾器、疊代器、生成器?

目錄

一、裝飾器

二、疊代器

三、生成器

好麻,最近整理下Python學習筆記,把面試常問的幾個裝飾器、疊代器、生成器總結一下。

一、裝飾器

裝飾器定義:裝飾器便于代碼複用, 将函數作為參數傳給裝飾器函數, 拓展原來函數功能的一種函數。

裝飾器作用:裝飾器就是在不修改被裝飾器對象源代碼以及調用方式的前提下為被裝飾對象添加新功能(增強函數功能但是又不修改原函數, 抽離函數中與函數本身無關的功能進行複用)。

應用場景:插入日志、性能測試、事務處理、 Web權限校驗、Cache等。

"""
1、無參函數裝飾器
把@funA放到funA_test()函數的定義處,相當于執行了語句:funA_test = funA(funA_test)
"""
def funA(func):
    print('1、裝飾器函數 funA 增強 %s()' % func.__name__)
    func()

@funA
def funA_test():
    print('1、原函數 funA_test')
    
funA_test()
    
輸出結果:
1、裝飾器函數 funA 增強 funA_test()
1、原函數 funA_test           

複制

"""
2、不定長參數函數裝飾器
wrapper()函數的參數定義是(*args, **kw),是以,wrapper()函數可以接受任意參數的調用。在wrapper()函數内,首先列印日志,再緊接着調用原始函數。
"""
def funB(func):
    def wrapper(*args, **kwargs):
        print('2、裝飾器函數 funB 增強 %s()' % func.__name__)
        func(*args, **kwargs)
    return wrapper


@funB
def funB_test(x, y):
    print('2、原函數 funB_test', x, '+', y, '=', x + y)
    
funB_test(2, 4)
       
輸出結果:
2、裝飾器函數 funB 增強 funB_test()
2、原函數 funB_test 2 + 4 = 6           

複制

二、疊代器

1、疊代器

疊代器定義:疊代器(Iterator)是通路集合内元素的一種方式,提供了一種周遊序列對象的方法。一個類(對象)隻要含有__iter__、__next__兩個方法,就将其稱為疊代器。

疊代器作用:疊代器最核心的功能就是可以通過__next__方法的調用來傳回下一個值。而這個值不是從已有的資料中讀取的,而是通過程式按照一定的規則生成的。這也就意味着我們可以不再依賴一個現存的資料集合來存放資料,而是邊用邊生成,這樣的好處就是可以節省大量的記憶體空間。

2、可疊代對象

一個對象隻要含有__iter__方法,就将其稱為可疊代對象。

Python可疊代對象有str(字元串)、list(清單)、tuple(元組)、dirt(字典)、set(集合)等。

3、總結

1.可疊代對象不一定是疊代器。

2.疊代器一定是可疊代對象。

3.容器類型(str list tuple dict set)是可疊代對象但不是疊代器。

# 定義一個疊代器
class IterDemo:
    def __iter__(self):
        self.a = 1
        return self  # __iter__ 方法傳回了執行個體本身 self,也就是說傳回了一個疊代器,是以 IterDemo 的執行個體 iterDemo 也是一個「可疊代對象」

    def __next__(self):
        x = self.a
        self.a += 1
        if self.a == 10:
            raise StopIteration()  # 異常用于辨別疊代的完成,防止出現無限循環的情況
        return x


def iter_demo():
    iterDemo = IterDemo()
    it = iter(iterDemo)  # 建立疊代器對象

    print('x = ', it.__next__())  # 輸出疊代器的下一個元素
    print('x = ', it.__next__())  # 輸出疊代器的下一個元素
    print('x = ', it.__next__())  # 輸出疊代器的下一個元素

    print('y = ', next(it))  # 輸出疊代器的下一個元素
    print('y = ', next(it))  # 輸出疊代器的下一個元素
    print('y = ', next(it))  # 輸出疊代器的下一個元素

    for i in it:
        print('z = ', i)

輸出結果:
x =  1
x =  2
x =  3
y =  4
y =  5
y =  6
z =  1
z =  2
z =  3
z =  4
z =  5
z =  6
z =  7
z =  8           

複制

# isinstance()檢查對象是否是 類/子類 的執行個體
def isinstanc_demo():
    lisTest = [1, 2, 3]  # 可疊代的
    lisTest1 = 1  # 不可疊代的
    print("判斷是否是可疊代的對象:", isinstance(lisTest, Iterable))  # Iterable(可疊代對象)
    print("判斷是否是疊代器:", isinstance(lisTest, Iterator))       # Iterator(疊代器)
    print("判斷是否是疊代器:", isinstance(IterDemo(), Iterator))    # Iterator(疊代器)


輸出結果:
判斷是否是可疊代的對象:True
判斷是否是疊代器:False
判斷是否是疊代器:True           

複制

def demo():
    listTest = ['a', 'b', 'c']

    # 疊代周遊
    it = iter(listTest)  # 建立疊代器對象
    print('x= ', it.__next__())

    print('y=', next(it))

    for i in it:
        print("z =", i)  # 輸出疊代器的下一個元素

    # 正常周遊
    for j in listTest:
        print("j =", j)
        
輸出結果:
x=  a
y= b
z = c
j = a
j = b
j = c           

複制

三、生成器

生成器定義:一邊循環一邊計算的機制,稱為生成器(generator)。生成器(generator)也是一種疊代器,在每次疊代時傳回一個值,直到抛出 StopIteration 異常。

生成器作用:清單所有資料都在記憶體中,如果有海量資料的話将會非常耗記憶體。如:僅僅需要通路前面幾個元素,那後面絕大多數元素占用的空間都白白浪費了。如果清單元素按照某種算法推算出來,那我們就可以在循環的過程中不斷推算出後續的元素,這樣就不必建立完整的list,進而節省大量的空間。

# 建立生成器方式1:把一個清單生成式的[]改成(),就建立了一個generator
# l是一個list,而g是一個generator
def demo():
    l = [x * x for x in range(10)]
    print(l)

    g = (x * x for x in range(10))

    print(g)  # 列印的是一個對象

    print('x =', next(g))
    print('x =', next(g))
    print('x =', next(g))

    print('y =', g.__next__())
    print('y =', g.__next__())
    print('y =', g.__next__())

    for i in g:
        print('z =', i)
        
    g.close()  # 關閉生成器

輸出結果:
x = 0
x = 1
x = 4
y = 9
y = 16
y = 25
z = 36
z = 49
z = 64
z = 81           

複制

# 建立生成器方式2:yield
def yield_demo():
    for i in range(10):
        yield i

def yield_demo_test():
    yie = yield_demo()

    print('x =', next(yie))
    print('x =', next(yie))
    print('x =', next(yie))

    print('y =', yie.__next__())
    print('y =', yie.__next__())
    print('y =', yie.__next__())

    for i in yie:
        print('z =', i)
        
輸出結果:
x = 0
x = 1
x = 2
y = 3
y = 4
y = 5
z = 6
z = 7
z = 8
z = 9           

複制

相關代碼已經放到 https://gitee.com/weimenghua/Learn-Python/tree/master/base,decorator_demo.py 、generator_demo.py 、iteration_demo.py。           

複制

總結:因為在自動化測試中,裝飾器是非常重要的,它可以幫助我們将一個公共部分抽象出來,有點類似于切面程式設計(AOP),可以讓開發者更專注于業務邏輯。疊代器和生成器可以節省大量記憶體空間,但這塊我還沒有深刻的了解。

https://www.processon.com/view/link/615eae81e0b34d06f3dcdf4b

【Python系列】為啥老問裝飾器、疊代器、生成器?