python 之装饰器

python 之装饰器

1、闭包

def line_conf(a, b):
    def line(x):
        return a*x + b
    return line

line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5))
print(line2(5))

# 函数名只是函数代码空间的引用,当函数名赋值给一个对象的时候 就是引用传递
# 闭包就是一个嵌套定义的函数,在外层运行时才开始内层函数的定义,然后将内部函数的引用传递函数外的对象
# 内部函数和使用的外部函数提供的变量构成的整体称为闭包

2、装饰器

2.1 装饰器(decorator)的应用场景

  1. 引入日志
  2. 函数执行时间统计
  3. 执行函数前预备处理
  4. 执行函数后清理功能
  5. 权限校验等场景
  6. 缓存

2.2 无参数的函数

from time import ctime, sleep

def timefun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()
    return wrapped_func

@timefun
def foo():
    print("I am foo")

foo()
sleep(2)
foo()

# 运行结果:
# foo called at Sat Mar 11 13:16:07 2023
# I am foo
# foo called at Sat Mar 11 13:16:09 2023
# I am foo

上面代码理解装饰器执行行为可理解成

foo = timefun(foo)
# foo先作为参数赋值给func后,foo接收指向timefun返回的wrapped_func
foo()
# 调用foo(),即等价调用wrapped_func()
# 内部函数wrapped_func被引用,所以外部函数的func变量(自由变量)并没有释放
# func里保存的是原foo函数对象

2.3 被装饰的函数有参数

from time import ctime, sleep

def timefun(func):
    def wrapped_func(a, b):
        print("%s called at %s" % (func.__name__, ctime()))
        print(a, b)
        func(a, b)
    return wrapped_func

@timefun
def foo(a, b):
    print(a+b)

foo(3,5)
sleep(2)
foo(2,4)

# 运行结果:
# foo called at Sat Mar 11 13:17:35 2023
# 3 5
# 8
# foo called at Sat Mar 11 13:17:37 2023
# 2 4
# 6

2.4 被装饰的函数有不定长参数

from time import ctime, sleep

def timefun(func):
    def wrapped_func(*args, **kwargs):
        print("%s called at %s"%(func.__name__, ctime()))
        func(*args, **kwargs)
    return wrapped_func

@timefun
def foo(a, b, c):
    print(a+b+c)

foo(3,5,7)
sleep(2)
foo(2,4,9)

# 运行结果:
# foo called at Sat Mar 11 13:18:24 2023
# 15
# foo called at Sat Mar 11 13:18:26 2023
# 15
2.5 装饰器中的return
from time import ctime, sleep

def timefun(func):
    def wrapped_func():
        print("%s called at %s" % (func.__name__, ctime()))
        func()  # return func()
    return wrapped_func

@timefun
def foo():
    print("I am foo")

@timefun
def getInfo():
    return '----hahah---'

foo()
sleep(2)
foo()

print(getInfo())

# 运行结果:
# foo called at Sat Mar 11 13:19:05 2023
# I am foo
# foo called at Sat Mar 11 13:19:07 2023
# I am foo
# getInfo called at Sat Mar 11 13:19:07 2023
# None

如果修改装饰器为return func(),则运行结果:

foo called at Sat Mar 11 13:21:10 2023
I am foo
foo called at Sat Mar 11 13:21:12 2023
I am foo
getInfo called at Sat Mar 11 13:21:12 2023
----hahah---

2.6 类装饰器

class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s"%func.__name__)
        self.__func = func
    def __call__(self):
        print("---装饰器中的功能---")
        self.__func()
#说明:
#1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
#   并且会把test这个函数名当做参数传递到__init__方法中
#   即在__init__方法中的属性__func指向了test指向的函数
#
#2. test指向了用Test创建出来的实例对象
#
#3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法
#
#4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
#   所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
@Test
def test():
    print("----test---")
test()
showpy()#如果把这句话注释,重新运行程序,依然会看到"--初始化--"

运行结果如下:

---初始化---
func name is test
---装饰器中的功能---
----test---

3 总结

1、装饰器函数只有一个参数就是被装饰的函数的应用
2、装饰器能够将一个函数的功能在不修改代码的情况下进行扩展
3、在函数定义的上方@装饰器函数名 即可直接使用装饰器对下面的函数进行装饰。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曾晶的总结

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值