装饰器

装饰器基础

装饰器的目的是为了给被装饰 对象,增加新功能,或者说增加某种能力

在程序中工具就是函数

如此一来,装饰器指的就是一个函数,被装饰着也是一个函数

总结;装饰器就是用一个函数去拓展另外一个已存在的函数的功能

       拓展性是对于一个应用程序来说非常重要的能力,任何应用程序都需要拓展,于是出现了开闭原则

开闭原则:

    对修改关闭,对拓展开放

    不允许修改源代码以及调用方式

    装饰器就是一种可以保证不修改源代码,也不修改调用方式,还能给函数添加新功能的方式

需求:  目前已有一个函数,其功能是从服务器下载一个文件,需求要为这个函数统计下载耗时

import   time(下载功能)

def download(filepath):

    print('开始下载%s’% filepath)

    time.sleep(3)

    print('下载完成%s’% filepath)

    return  '123'

def upload():

    print('开始上传’)

    time.sleep(3)

    print('上传完成’)

    return  '123'

def outer(func)

    def run_time(*args ,**kwargs )

        boot_time=time.time()

         res=func(*args,**kwargs)

         print('耗时',time.time()-boot_time)

         return res

    return run_time

download = outer(download)

movie = download('大电影’)

print(movie)

upload=outer(upload)

upload()

无参函数:

import time
def download():
print("download run!")

# ===============================
def outer(func):
def run_time(*args,**kwargs): #是为了让装饰函数能接受任何形式任何长度的参数
boot_time = time.time()
res = func(*args,**kwargs) # 将参数在原模原样交给被装饰者
print("耗时:", time.time() - boot_time)
return res # 把原始函数的执行结果 在交给调用者
return run_time
download = outer(download)
# ==============================

# 使用者
download()

有参函数
from functools import wraps
import time
def outer(location):
def logger(func):
@wraps(func) # wrapper.__doc__ = func.__doc__
def wrapper(*args, **kwargs):
"""这是装饰器函数"""
if location == "cmd":
print("时间:%s func:%s" % (time.time(), func.__name__))
elif location == "file":
with open("a.log", "a", encoding="utf-8") as f:
f.write("时间:%s func:%s" % (time.time(), func.__name__))
else:
print("位置错误........必须是 file 或 cmd")
return func(*args, **kwargs)
return wrapper
return logger

@outer("file") # ????? logger = outer("file) test = logger(test)
def test():
"""这是一个test函数"""
print("test run!")

# test()
print(test.__doc__)(功能是调出注释)

装饰器语法糖
"""
语法糖
就是一种简便写法,使你的语法更简洁

"""
# 提供输出日记(日志 什么时候干了什么事)功能
import time
def logger(func):
def wrapper(*args,**kwargs):
print("时间:%s func:%s" % (time.time(),func.__name__))
res = func(*args,**kwargs)
return res
return wrapper

# 该语法就可以帮我们完成对原始函数的伪装,
# 注意 1.必须写在被装饰函数的正上方
# 注意 2.在开发时装饰器必须写在被装饰函数之上
@logger # login = logger(login)
def login():
print("登录成功...")
login()
装饰器在购物车中的使用
is_login = False

# 判断是否登录过的装饰器
def auth(func):
def wrapper(*args,**kwargs):
if is_login:
func(*args,**kwargs)
else:
print("还没有登录过请先登录...")
login()
return wrapper


def login():
global is_login
name = input("name:").strip()
pwd = input("pwd:").strip()
if name == "blex" and pwd == "123":
print("登录成功!")
is_login = True

@auth
def shopping():
print("查看购物车....")

@auth
def collection():
print("查看收藏....")


def main():
while True:
funcs = {"1":login,"2":shopping,"3":collection}
print("""
1.登录
2.购物车
3.收藏夹
""")
res = input(">>>:").strip()
if res in funcs:
funcs[res]()
else:
print("输入有误!")
main()


同时叠加多个装饰器
import time
# 装饰器1
def logger(func):
def wrapper(*args,**kwargs):
print("时间:%s func:%s" % (time.time(),func.__name__))
res = func(*args,**kwargs)
return res
return wrapper

#装饰器2
def timer(func):
def run_time(*args,**kwargs):
boot_time = time.time()
res = func(*args,**kwargs) # 这是在执行原始的download函数也就是被装饰的函数
print("耗时:", time.time() - boot_time)
return res # 把原始函数的执行结果 在交给调用者
return run_time


# 该语法就可以帮我们完成对原始函数的伪装,
# 注意 1.必须写在被装饰函数的正上方
# 注意 2.在开发时装饰器必须写在被装饰函数之上
@timer # logger = timer(logger)
@logger # login = logger(login)
def login():
print("登录成功...")
login()
# 在嵌套多个装饰器时,执行的顺序是 从上往下依次调用,结束的顺序反过来,是从下往上
# 实际开发中 没什么用.....
小节
1.装饰器
什么是装饰器,一种为其他函数增加新功能的函数就是装饰器
装饰器是基于闭包函数实现的
可以在遵循开闭原则的前提下,扩展新功能

无参:
def outer(func):
def wrapper(*args,**kwargs):
# 新功能
res = func(*args,**kwargs)
return res
return wrapper

有参
def big_outer(arg):
def outer(func):
def wrapper(*args,**kwargs):
# 新功能
res = func(*args,**kwargs)
return res
return wrapper
return outer
 
 
 


原文地址:https://www.cnblogs.com/tangda/p/10272183.html