1. 程式人生 > 其它 >緣起,在人群中,我看見你---------------裝飾器

緣起,在人群中,我看見你---------------裝飾器

裝飾器

裝飾器的定義(what why how)

1.什麼是裝飾器
	裝飾器就是裝飾某一個東西的工具
2.為什麼要用裝飾器
	因為在源函式程式碼不改變呼叫方法&原始碼給原函式新增新功能,裝飾器是最好的解決工具
3.怎麼用裝飾器
	詳見下面

裝飾器的實現思路

"""
	現有一個原函式index,想要為其新增一個時間差的功能,我們應該怎麼做呢
"""

# 方案一  這就已經修改了他的原始碼了
	import time


    def index(x):
        start_time = time.time()
        print(f'welcome to index {x}')
        time.sleep(3)
        print(time.time() - start_time)

    index(1)
# 方案二 沒有修改原函式的程式碼&呼叫,但是程式碼冗餘
    def index(x):
        print(f'welcome to index {x}')
        time.sleep(3)


    start_time = time.time()
    index(1)
    print(time.time() - start_time)

    start_time = time.time()
    index(1)
    print(time.time() - start_time)


# 方案三 解決了程式碼冗餘問題,但是原函式的呼叫我們修改了,而且wrapper寫死了,只能呼叫index
    def index(x):
        print(f'welcome to index {x}')
        time.sleep(3)


    def wrapper():
        start_time = time.time()
        index(1)
        print(time.time() - start_time)


    wrapper()


# 方案四 我們先搞定呼叫index函式寫死問題
    def index(x):
        print(f'welcome to index {x}')
        time.sleep(3)


    def outter(func):
        def wrapper():
            start_time = time.time()
            func(1)
            print(time.time() - start_time)

        return wrapper


    index = outter(index)
    index()


# 方案五  然後在搞定index函式引數問題
    def index(x):
        print(f'welcome to index {x}')
        time.sleep(3)


    def outter(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            func(*args, **kwargs)
            print(time.time() - start_time)

        return wrapper


    index = outter(index)
    index(11)


# 方案六  在搞定index返回值的問題,這樣就把wrapper偽裝成index偽裝的很好了
    def index(x):
        print(f'welcome to index {x}')
        time.sleep(3)
        return 123


    def outter(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            print(time.time() - start_time)
            return res

        return wrapper


    index = outter(index)
    res = index(11)
	print(res)


# 方案七 在讓wrapper更像index一點
    def index(x):
        """
        這是index的配置資訊
        """

        print(f'welcome to index {x}')
        time.sleep(3)
        return 123


    def outter(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            print(time.time() - start_time)
            return res

        wrapper.__name__ = index.__name__
        wrapper.__doc__ = index.__doc__
        return wrapper


    index = outter(index)
    res = index(11)
    print(res)


# 語法糖
    def outter(func):
        from functools import wraps
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            print(time.time() - start_time)
            return res

        return wrapper


    @outter
    def index(x):
        """
        這是index的配置資訊
        """

        print(f'welcome to index {x}')
        time.sleep(3)
        return 123


    res = index(11)
    print(res)

裝飾器的總結模板

# 無參裝飾器
def outter(func):
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return wrapper

# 有參裝飾器
def outter(x):
    def foo(func):
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            return res
        return wrapper
   	return foo

多個裝飾器

import time


def deco1(func):
    print('----deco1')

    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        print(time.time() - start_time)
        return res

    return wrapper()


def deco2(func):
    print('----deco2')

    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        print(time.time() - start_time)
        return res

    return wrapper()


@deco1
@deco2
def index(x):
    print(f'{x}')
'''
	當多個裝飾器疊加的時候 例如這樣是先從上而下去執行,但是返回值則是從下而上的去返回 所以deco2的返回值是在deco1,deco1的返回值是在真正的index上
'''

有參裝飾器

def login():
    name = input('name is :').strip()
    pwd = input('pwd is :').strip()

    if name == 'ycc' and pwd == '123':
        print('login successful')
    else:
        print('name or pwd error')

def auth(db_type):
    def deco(func):
        def wrapper(*args,**kwargs):

            if db_type == 'file':
                login()
                print('基於檔案驗證')
                # res = func(*args,**kwargs)
                # return res
            elif db_type == 'mysql':
                login()
                print('基於資料庫驗證')
                # res = func(*args, **kwargs)
                # return res

            elif db_type == 'ldap':
                login()
                print('基於ldap驗證')
                # res = func(*args, **kwargs)
                # return res
            res = func(*args, **kwargs)
            return res
        return wrapper
    return deco


@auth(db_type='file')
def index(x, y):
    print(x, y)


@auth(db_type='mysql')
def home(name):
    # print('welcome %s to home page'%name)
    print(f'welcome {name} to home page')
    return name


@auth(db_type='ldap')
def transfer():
    print('transfer')


index(1, 2)
name = home('ycc')
print(name)