裝飾器 迭代器

裝飾器

有參裝飾器的實現

瞭解無參裝飾器的實現原理後,咱們能夠再實現一個用來爲被裝飾對象添加認證功能的裝飾器,實現的基本形式以下python

def deco(func):
    def wrapper(*args, **kwargs):
        #編寫基於文件的認證,認證經過則執行res=func(*args, **kwargs),並返回res
    return wrapper

若是咱們想提供多種不一樣的認證方式以供選擇,單從wrapper函數的實現角度改寫以下mysql

def deco(func):
    def wrapper(*args, **kwargs):
        if driver == 'file':
            print('基於文件認證經過')
            res = func(*args, **kwargs)
            return res
        elif driver == 'mysql':
            print('基於數據認證經過')
            res = func(*args, **kwargs)
            return res
        print('...')
    return wrapper

函數wrapper須要一個driver參數,而函數deco與wrapper的參數都有其特定的功能,不能用來接受其餘類別的參數,能夠在deco的外部再包一層函數auth,用來專門接受額外的參數,這樣便保證了在auth函數內不管多少層均可以引用到sql

def auth(driver):
    def deco(func):
        def wrapper(*args, **kwargs):
            if driver == 'file':
                print('基於文件認證經過')
                res = func(*args, **kwargs)
                return res
            elif driver == 'mysql':
                print('基於數據認證經過')
                res = func(*args, **kwargs)
                return res
        print('...')
        return wrapper
    return deco


@auth(driver='aaa')#這裏由於咱們傳入的參數沒有
#下面爲該語法糖最後表明的內容
#--->@和auth(driver='aaa')--->而auth(driver='aaa')至關因而調用函數auth獲得結果爲deco函數的內存地址,即此時這裏爲@deco,這裏咱們也能夠將其分開爲@和deco--->而@的做用就是至關於將被裝飾對象的函數名看成參數傳入該函數,因此如今就爲deco(index),而該函數的結果爲wrapper,因此這裏咱們能夠寫爲wrapper=deco(index),即wrapper=wrapper  --->因此最後咱們調用的函數實際上是wrapper,可是裝飾器的原則之一爲不修改被裝飾對象的調用方式,因此咱們能夠將wrapper函數對應的內存地址定義一個變量index=wrapper。
def index():
    print('from index')
    
index()
#輸出結果爲
...

可使用help(函數名)來查看函數的文檔註釋,本質就是查看函數的__doc__屬性,但對於被裝飾以後的函數,查看文檔註釋app

import time
def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print('run time is %s'%(end_time - start_time))
        return res
    return wrapper

@timer
def home(name):
    '''
    home page function
    :param name:str
    :return:None
    '''
    time.sleep(5)
    print('Welcome to the home pae', name)
print(help(home))
#輸出結果爲
Help on function wrapper in module __main__:

wrapper(*args, **kwargs)

None

Process finished with exit code 0

在被裝飾以後home=wrapper,查看home.__name__也能夠發現home的函數名確實是wrapper,想要保留原函數的文檔和函數名屬性,須要修正裝飾器函數

def timer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    wrapper.__doc__=func.__doc__
    wrapper.__name__=func.__name__
    return wrapper

按照上述方式來實現保留原函數屬性過於麻煩,functools模塊下提供一個裝飾器wraps專門用來幫咱們實現這件事,用法以下工具

from functools import wraps

def timer(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper

迭代器

迭代器
迭代的工具。code

迭代:
        迭代指的是重複迭代,每一次迭代都是基於上一次的結果而來的。

    迭代器:
        迭代器指的是迭代取值的工具,它能夠迭代取值。

    - 若是想要知道python中迭代器是什麼?必須先知道什麼是可迭代對象?

    - 可迭代對象:  全部的序列類型: str, list, tuple, dict, set, f
        凡是內部有str.__iter__()方法的都是可迭代對象。

    - 獲取迭代器:
        經過可迭代對象.__iter__(), 獲得的返回值就是 「迭代器對象」。
        迭代器是迭代取值的工具,做用是迭代取值。

    - 如何迭代取值:
        迭代器對象.__next__()  # 「每一次執行」,都會從迭代器對象中取出一個值


    - 總結: 可迭代對象 VS 迭代器對象:
        - 獲取可迭代對象: 定義序列類型(str, list, set, tuple, dict, f)
            - 特色:
                內置有__iter__()

        - 獲取迭代器對象: 經過可迭代對象調用.__iter__()獲得返回值
            - 特色:
                內置有__next__()

    - 迭代器對象的優勢:
        - 優勢:
            1.不依賴於索引迭代取值。
            2.節省內存空間。

        - 缺點:
            1.取指定某個值麻煩
            2.每次取值都要從第一個值開始,沒法同過索引取值。


    for循環原理
        語法:     for i in 可迭代對象:
        in: 可迭代對象 ----> 內部會自動調用.__iter__() ---> 迭代器對象
        for line in list1:
            # 迭代器對象.__next__()



    - 迭代器本質上是一個可迭代對象

    - 文件本質上既是迭代器對象,也是可迭代對象。

    - 可迭代對象不必定是迭代器對象
相關文章
相關標籤/搜索