1. 程式人生 > 實用技巧 >Python3 裝飾器無參有參 Egon老師視訊

Python3 裝飾器無參有參 Egon老師視訊

# 一:儲備知識
#1、 *args, **kwargs
# def index(x,y):
# print(x,y)
#
#
# def wrapper(*args,**kwargs):
# index(*args,**kwargs) #
# # index(y=222,x=111)
# wrapper(y=222,x=111)


# 2、名稱空間與作用域:名稱空間的的"巢狀"關係是在函式定義階段,即檢測語法的時候確定的

# 3、函式物件:
# 可以把函式當做引數傳入
# 可以把函式當做返回值返回
# def index():
# return 123

#
# def foo(func):
# return func
#
# foo(index)

# 4、函式的巢狀定義:
# def outter(func):
# def wrapper():
# pass
# return wrapper


# 閉包函式
# def outter():
# x=111
# def wrapper():
# x
# return wrapper
#
# f=outter()

#二 裝飾器
"""
1、什麼是裝飾器
器指的是工具,可以定義成成函式
裝飾指的是為其他事物新增額外的東西點綴

合到一起的解釋:

裝飾器指的定義一個函式,該函式是用來為其他函式新增額外的功能


2、為何要用裝飾器
開放封閉原則
開放:指的是對拓展功能是開放的
封閉:指的是對修改原始碼是封閉的

裝飾器就是在不修改被裝飾器物件原始碼以及呼叫方式的前提下為被裝飾物件新增新功能
3、如何用

總結無參裝飾器模板
# def outter(func):
# def wrapper(*args,**kwargs):
# # 1、呼叫原函式
# # 2、為其增加新功能
# res=func(*args,**kwargs)

# return res
# return wrapper

作業

import time
from functools import wraps


def outter(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        res = 0

        while 1 > 0:
            name = input("username is:").strip()
            pwd = input("password is ").strip()
            while (time.time() - start) < 20:
                if name == "yun" and pwd == "123":
                    time.sleep(20)
                    res = func(*args, **kwargs)
                else:
                    print("ipunt wrong")
                end = time.time()
                print('run tiem is %f'%(end - start))
        return res

    return wrapper

@outter #index = outter(index) ==> index = wrapper
def index(x,y,z):
    print("%s %s %s"%(x,y,z))


    
index(1,2,3)
print(index.__repr__())

# 一:知識儲備
# 由於語法糖@的限制,outter函式只能有一個引數,並且該才是只用來接收
# 被裝飾物件的記憶體地址
# def outter(func):
# # func = 函式的記憶體地址
# def wrapper(*args,**kwargs):
# res=func(*args,**kwargs)
# return res
# return wrapper
#
# # @outter # index=outter(index) # index=>wrapper
# @outter # outter(index)
# def index(x,y):
# print(x,y)

# 偷樑換柱之後
# index的引數什麼樣子,wrapper的引數就應該什麼樣子
# index的返回值什麼樣子,wrapper的返回值就應該什麼樣子
# index的屬性什麼樣子,wrapper的屬性就應該什麼樣子==》from functools import wraps

# 語法糖
def auth(db_type):
def deco(func):
def wrapper(*args, **kwargs):
name = input('your name>>>: ').strip()
pwd = input('your password>>>: ').strip()

if db_type == 'file':
print('基於檔案的驗證')
if name == 'egon' and pwd == '123':
res = func(*args, **kwargs) # index(1,2)
return res
else:
print('user or password error')
elif db_type == 'mysql':
print('基於mysql的驗證')
elif db_type == 'ldap':
print('基於ldap的驗證')
else:
print('不支援該db_type')
return wrapper
return deco


@auth(db_type='file') # @deco # index=deco(index) # index=wrapper
def index(x, y):
print('index->>%s:%s' % (x, y))

@auth(db_type='mysql') # @deco # home=deco(home) # home=wrapper
def home(name):
print('home->>%s' % name)


@auth(db_type='ldap') # 賬號密碼的來源是ldap
def transfer():
print('transfer')

# index(1, 2)
# home('egon')
# transfer()


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

@有參裝飾器(1,y=2,z=3)
def 被裝飾物件():
pass

作業:編寫日誌裝飾器,實現功能如:一旦函式f1執行,則將訊息2017-07-21 11:12:11 f1 run寫入到日誌檔案中,日誌檔案路徑可以指定

import time
#time.strftime('%Y-%m-%d %X')

path = input("檔案路徑:").strip()
def zuiz(file_path):
    def outter(func):
        def f1_w(*args, **kwargs):
            with open(file_path, 'w') as f:
                f.write(time.strftime('%Y-%m-%d %X'))
            res = func(*args, **kwargs)
            return res
        return f1_w
    return outter

@zuiz(path)
def index(x,y,z):
    print("%s %s %s"%(x,y,z))
    return 1

index(1,2,3)