python装饰器

- 装饰器本质

装饰器本质就是一个修饰其他函数的函数,为其他函数添加附加功能

- 装饰器要把握的2个原则

1.不修改被修饰函数的源代码
2.不修改被修饰函数的调用方式

- 装饰器的实现

装饰器 = 高阶函数+函数嵌套+闭包

满足下面任何一个条件都是高阶函数:
(1)函数接收的参数是一盒函数名
(2)函数的返回值是一个函数名

函数嵌套:父函数里面还有子函数
闭包:作用域的一种体现,一层套一层(一层一个函数),给最外层传一个参数,可以一直渗透到最里层
在这里插入图片描述

  • 只用高阶函数例子:给函数加上统计运行时间的功能
# 方式一:修改了调用方式
import time
def foo():
    print("你好")

def test(func):
    start_time = time.time()
    print(func)
    func()
    stop_time = time.time()
    print("函数%s的运行时间为%s;但是函数调用方式从foo()变成了test(foo)" % (func.__name__, stop_time-start_time))

test(foo)
# 方式二:虽然没有修改调用方式,但是foo1函数被调用了两次func
import time
def foo1():
    print("你好")

def test1(func):
    start_time = time.time()
    print(func)
    func()
    stop_time = time.time()
    print("函数%s的运行时间为%s;但是函数调用方式从foo()变成了test(foo)" % (func.__name__, stop_time-start_time))
    return func

foo1 = test1(foo1)
foo1()
  • 高阶函数+函数嵌套实现基本的装饰器架子
# 装饰器架子
def func():
	pass

def timmer(func):
	def wrapper():
		# 函数执行前操作
		func()
		# 函数执行后操作
	return wrapper

func = timmer(func)
func()
  • 高阶函数+函数嵌套实现基本的装饰器:给函数加上统计运行时间的功能
import time
def func():
	print("in func")
	time.sleep(2)

def timmer(func):
	def wrapper():
		start_time = time.time()
		func()
		stop_time = time.time()
		print("函数%s的运行时间为%s;但是函数调用方式从foo()变成了test(foo)" % (func.__name__, stop_time-start_time))
	return wrapper
	
func = timmer(func) # 这一句等价于在func定义上面加上@time
func()		

- 装饰器优化:带参数和返回值的装饰器

'''
func = timmer(func)
func(1,2,3)
func=timmer(func)的返回值是wrapper函数,给func加参数等价于给wrapper加参数
所以func(*args, **kwargs) => wrapper(*args, **kwargs)

func的返回值要在wrapper中接收一下,再return回去

'''
def timmer(func):
    # 函数嵌套
    def wrapper(*args, **kwargs):
        start_time = time.time()
        print(func)
        res = func(*args, **kwargs) # 参数+返回值
        stop_time = time.time()
        print("%s函数运行时间为%s" % (func.__name__, stop_time-start_time))
        return res
    return wrapper # 高阶函数

def func(*args, **kwargs):
    time.sleep(1)
    print(args, kwargs)
    print("in func")


func = timmer(func)
res = func(1,2,3)
print(res)

- 修改成@的方式

def timmer(func):
    # 函数嵌套
    def wrapper(*args, **kwargs):
        start_time = time.time()

        res = func(*args, **kwargs)
        stop_time = time.time()
        duration = stop_time-start_time
        print("%s函数运行时间为%s" % (func.__name__, duration))
        return res
    return wrapper # 高阶函数

@timmer # 等价于 func = timmer(func)
def func(*args, **kwargs):
    time.sleep(1)
    print("in func")
    print(args, kwargs)
    return (args, kwargs)

print(func(1, 2, 3))

- 带参数的装饰器–实现认证类型选择

def auth(auth_type="file_auth"):
	def dec_auth(func):
	    def wrapper(*args, **kwargs):
	        # 验证功能
	        print("你输入的认证类型是%s" % auth_type)
	        username = input("用户名:").strip()
	        passwd = input("密码:").strip()
	        if username == "root" and passwd == "123":
	            res = func(*args, **kwargs)
	            return res
	        else:
	            print("用户名密码错误")
	    return wrapper
	return dec_auth
    
# 下面的过程分以下步骤
# (1) auth(auth_type="db_auth")=>dec_auth
# (2)@auth(auth_type="db_auth")  ==》 car = auth(auth_type="db_auth")=dec_auth(car)
@auth(auth_type="db_auth") 
def car(name):
    print("欢迎来到%s的购物车"%name)

car("ybp")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值