048 裝飾器

裝飾器

  • 器:只的就是工具
  • 函數:也能夠說是一個工具,須要用到這個工具的時候能夠直接拿過來用
  • 裝飾器:是指對一個工具備裝飾的做用,也就是說能夠爲一個工具添加其餘的功能做用
  • 因此定義裝飾器其實就是至關於在定義一個函數,只不過這個函數的功能是用來爲其餘函數添加額外的功能
  • 裝飾器至關於一個函數A,它用來裝飾另外一個函數B,爲函數B添加其餘的功能,這就是用一個函數A去裝飾另外一個函數B

1、無參裝飾器

1.爲何要使用裝飾器

  • 就比如咱們已經完成了一個項目,可是咱們須要修改其中某個方法,可是咱們又不想修改他原來的

調用方法,那這個時候咱們就可使用裝飾器來實現修改python

  • 使用裝飾器的時候咱們須要遵循兩點原則
    • 不修改被裝飾對象的源代碼
    • 不修改被裝飾對象的調用方式

2.改變源代碼方式修改函數的功能

# 原函數
def name():
    print('hello xichen')
name


# 爲原函數增長功能
# 修改源代碼的方式
def name():
    print('---------')
    print('hello xichen')
    print('---------')
name()

3.修改調用方式

import time

def index():
    print('welcome to index')
    time.sleep(1)


def func(func):
    start = time.time()
    fun()
    end = time.time()
    print(start-end)

func(index)

4.用裝飾器來修改

# 沒有返回值的
import time

def index():
    print('welcome to index')
    time.sleep(1)

def func(fun):
    def f():# 從新建立的index
        start = time.time()
        fun() # 真正的index
        end = time.time()
        print(start-end)
    return f
index = func(index) # index = func(),其實就是等於f()
index()
# 有返回值的
import time

def index():
    print('welcome to index')
    time.sleep(1)
    
    return 123

def func(fun):
    def f():# 從新建立的index
        start = time.time()
        res = fun() # 真正的index
        end = time.time()
        print(start-end)
        return res
        
    return f
index = func(index) # index = fun,其實就是等於f()
res = index()
print(res)

5.完善的裝飾器

  • 若是原始的index()有返回值的時候,那麼咱們用裝飾器爲其添加的功能的最後返回值也應該和原函數的返回值相同
  • 因此這個時候咱們就能夠哪個變量來接收裝飾器最後的值而且返回
  • 也就是說咱們須要同步原始的函數返回值和咱們後來新建的一個添加功能的函數的返回值
import time

def func(fun):
    def f():
        start = time.time()
        res = fun()
        end = time.time()
        print(end - start)
        return res
    return f

def index():
    print('hello xichen')
    time.sleep(1)

    return 123

index = func(index)
res = index()
print(res)
  • 若是原始的index()方法須要傳參,那麼咱們以前的裝飾器是沒法實現該功能的,因爲有後來新建的添加功能的函數就是=index(),因此給後來新建的函數方法傳參便可。
import time
def func(fun):
    def f1(*args, **kwargs):
        print('args:', args)
        print('kwargs:', kwargs)
        start = time.time()
        res = fun(*args, **kwargs)
        end = time.time()
        print(end - start)
        return res
    return f1

@func
def index(a,b=1):
    print('a:', a)
    print('b', b)
    print('hello xichen')
    time.sleep(1)

    return 123

res = index(1)
print(res)

6.裝飾器語法糖

  • 在被裝飾函數正上方,而且是單獨一行寫上@裝飾器名
  • 用語法糖的話會更精簡代碼,並且往後咱們用的裝飾器都是已經定義好的,能夠直接拿過來用
import time

def func(fun):
    def f(*args, **kwargs):
        print('args:', args)
        print('kwargs:', kwargs)
        start = time.time()
        res = fun(*args, **kwargs)
        end = time.time()
        print(end - start)
        return res
    return f
@func
def index(a,b=1):
    print('a:', a)
    print('b', b)
    print('hello xichen')
    time.sleep(1)

    return 123

res = index(1)
print(res)

7.裝飾器模板

  • 咱們只要記住了裝飾器的模板,其實就等於已經會了如何去用裝飾器了
def func(fun):
    def f(*args,**kwargs):
        res = fun(*args,**kwargs)
        # 給原來的函數加功能
        return res
    return f

2、有參的裝飾器

1.有參的三層裝飾器

def data(enter):
    def func(fun):
        def f(*args,**kwargs):
            if enter == 'file':
                uname = input('uname:')
                upwd = input('upwd:')
                if uname == 'xichen' and upwd == '123':
                    print('登錄成功')
                    res = fun(*args,**kwargs)
                    return res
                else:
                    print('登陸失敗')
            else:
                print('數據來源數據庫,不可用')
        return f
    return func
@data('file')
def shopping():
    print('歡迎shopping')
    return 123

res = shopping()
print(res)

2.雙層裝飾器

def demo2(func2):
    def add_func2(*args,**kwargs):
        print('-------------')
        func2(*args,**kwargs) # func2此時是demo1裝飾的函數add,添加的功能的add_func1
        print('-------------')

        return func2
    return add_func2


def demo1(func1):
    def add_func(*args,**kwargs):
        print('***********')
        func1(*args,**kwargs) # func1是被demo裝飾的函數add
        print('***********')

        return func1
    return add_func

def add():
    print('hello')

# 先運行的是先裝飾的函數demo1
add = demo1(add) # add = func1,也就是在調用add_func1,add返回的是add_func1
add = demo2(add) # add = func2,也就是在調用add_func2,add返回的是add_func2
add()

3.雙層裝飾器模板

def demo2(fun2):
    def add_func2(*args,**kwargs):
        res = fun2(*args,**kwargs)
        # 添加功能
        
        return res
    return add_fun2


def demo1(fun1):
    def add_func1(*args,**kwargs):
        res = fun1(*args,**kwargs)
        # 添加功能
        
        return res
    return add_fun1


def add():
    print('hello xichen')
    
    return 123


add = demo1(add)
add = demo2(add)
add()

4.三層裝飾器模板

def demo(enter):
    def func(fun):
        def f(*args,**kwargs)
            # 添加功能
            res = fun(*args,**kwargs)
        return f
    return func

@demo(參數---enter)
def add()
    print('hello xichen')
    
    return 123

res = add()
res()
  • 因爲兩層的裝飾器,參數必須得固定位func,可是三層的裝飾器解除了這個限制。咱們不單單可使用單個參數的三層裝飾器,多個參數的只須要在三層裝飾器中多加入幾個參數便可。也就是說裝飾器三層便可,多加一層反倒無用。
相關文章
相關標籤/搜索