python中msg函数_Python 中闭包函数和装饰器

一、闭包函数的概述

闭包 closure, 是一种代码的组织结构。当一个内嵌函数引用其外部作用域的变量,就形成一个闭包函数。闭包函数有一个内嵌函数,内嵌函数引用外部函数中的变量,外部函数的返回值是内嵌函数。

闭包是函数和所引用环境变量的组合体。闭包让函数持有状态,延长环境变量的生命周期。类似类里的类变量,可以用函数或类的__call__方法实现装饰器。闭包函数只是绑定自由变量,并不会立即执行。只有当闭包函数执行时,才会访问所引用的目标对象。

闭包函数加载的时候会访问闭包函数外部的代码,再次调用闭包函数的返回时执行闭包函数内部的代码。比如闭包函数的延迟绑定,闭包函数嵌套的匿名函数在外部函数访问时不会触发,会当作整体传递出去,只有再次调用才会触发函数体的执行。

优点是具备封装性,可实现隐式上下文管理,并减少参数,在设计上可替代部分全局变量,或将环境与调用接口分离。

缺点是对自由变量隐式依赖,会提升代码的复杂度。自由变量的生命周期变长,会提升内存的占用。

二、装饰器的概述

我们需要遵守开放封闭原则。

开放封闭原则:程序上线以后就应该对修改封闭,对扩展开放

修改封闭:不能修改功能性函数的源代码,不能修改功能性函数的调用方式

扩展开放:可以为原有的功能添加新功能

三、使用闭包函数完成装饰器的逐步实现

首先,我们定义一个函数

importtime, randomdefmsg():print('I have something to tell you, please wait a moment.')

time.sleep(random.randint(1, 5))print('I like you.')

msg()

该函数会随机休眠1-5秒钟。

现在,我们想要给该函数增加一个计时的功能,看看函数具体运行了多久。

importtime, randomdefmsg():print('I have something to tell you, please wait a moment.')

time.sleep(random.randint(1, 5))print('I like you.')

start_time=time.time()

msg()

stop_time=time.time()print('Run time is %s' % (stop_time - start_time))

并且如果要重复使用计时功能,就要写重复代码,所以我们想到了将计时功能封装成一个函数

defwrapper():

start=time.time()

msg()

stop=time.time()print('Run time is %s' % (stop -start))

wrapper()

我们将wrapper函数写死了,只能对内部调用的msg函数进行计时,使用闭包函数

deftimmer(func):defwrapper():

start=time.time()

func()

stop=time.time()print('Run time is %s' % (stop -start))return wrapper #将wrapper函数的内存地址作为返回值返回。

msg = timmer(msg) #作为参数的msg是我们定义的msg函数的内存地址

#作为变量名的msg是指向wrapper函数的内存地址

msg() 此时我们这样写看似在调用msg函数,但实际上是调用了wrapper函数

这样子我们就实现了偷梁换柱,在外观上没有更改msg函数的调用方式。

当传入的函数有参数或者有返回值时

deftimmer(func):def wrapper(*args, **kwargs):

strat_time=time.time()

res= func(*args, **kwargs)

stop_time=time.time()returnresreturn wrapper

装饰器的使用方法:语法糖

importtime, randomdeftimmer(func):def wrapper(*args, **kwargs):

strat_time=time.time()

res= func(*args, **kwargs)

stop_time=time.time()returnresreturnwrapper

@timmerdefmsg():print('I have something to tell you, please wait a moment.')

time.sleep(random.randint(1, 5))print('I like you.')

msg()

含参装饰器,含参装饰器是一个三层的闭包函数

importtimedeftimemer(partment):deffunc(func_1):def wrapper(*args,**wkargs):if partment=='task1':

start=time.time()

func_1(*args, **wkargs)

stop=time.time()print("the task1 run time is :", stop -start)elif partment=='task2':

start=time.time()

func_1(*args, **wkargs)

stop=time.time()print("the task2 run time is :", stop -start)returnwrapperreturnfunc

@timemer(partment='task1')deftask1():

time.sleep(2)print("in the task1")

@timemer(partment='task2')deftask2():

time.sleep(2)print("in the task2")

task1()

task2()

类实现的含参装饰器

from functools import wraps

classdecorate:def __init__(self, name):

self.name=name    # 装饰器的参数def __call__(self, func):

@wraps(func)def deco(*args, **kwargs):if self.name == 'Admin':passelif self.name == 'Student':passelif self.name == 'Teacher':passreturn func(*args, **kwargs)return deco

@decarate('Admin')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值