python 闭包函数_python中装饰器之闭包函数(一)

闭包函数

'''闭包函数:

1、闭包函数必须在函数内部定义

2、闭包函数可以引用外层函数的名字

闭包函数是函数对象、函数嵌套、名称空间与作用域的结合体'''

#直接传参

deffunc(x):print(x)#通过闭包函数传参

defwrapper(x):definner():print(x)returninner

func= wrapper(100) #>>返回inner的内存地址>>>>保存在func中

func()

闭包函数定义

#闭包函数的应用

importrequests#直接传参

defspider_func(url):

response=requests.get(url)if response.status_code == 200:print(len(response.text))#闭包函数chuanc

defspider_outer(url):defspider_inner():

response=requests.get(url)if response.status_code == 200:print(len(response.text))returnspider_inner

url1= 'https://www.baidu.com/'url2= 'https://www.cnblogs.com/xiaoyuanqujing'spider_baidu=spider_outer(url1)

spider_blog=spider_outer(url2)

spider_baidu()

spider_blog()

spider_outer(url1)

闭包函数的应用

装饰器

'''装饰器

不修改原函数的源代码

不修改原函数的调用方式

被装饰对象:即需要添加功能的函数

装饰器:被装饰函数添加的新功能的函数'''

例子:假设我们现在有一个函数,我们要为其添加一个统计执行时间的功能

defdownload_movie():print('Start downloading.....')

time.sleep(3)print('Download completed.....')

讲道理我们是这么执行的

#不使用装饰器

start_time =time.time()

download_movie()

stop_time=time.time()print(f'Running time is {stop_time - start_time}....')

问题虽然解决了,但针对每个需要添加统计时间功能的函数,都得敲一遍代码。这显然不符合python所要求的简洁优雅~

所以我们考虑:

#使用装饰器(无返回值时)

deftimer(func):definner():

start_time=time.time()

func()#>>>>>被装饰对象<<<<<

stop_time =time.time()print(f'Running time is {stop_time - start_time}....')returninner

timer(download_movie)#>>>>>>>>>> 返回inner

download_movie = timer(download_movie) #>>>>>>>>>>>以变量名download_movive接收inner

download_movie()

问题似乎解决了,然鹅,如果被装饰对象有返回值,如:

defdownload_movie():print('Start downloading.....')

time.sleep(3)print('Download completed.....')return 'Aoi.avi' #当被装饰对象有返回值时,上述装饰器需做修改

我们好像就得不到被装饰对象执行结束后返回的值的,这显然没有什么软用。于是修改装饰器

deftimer(func):definner():

start_time=time.time()

res= func() #>>>>>>>>>>>用res接收func()产生的返回值<<<<<<<<<<<<<<<

stop_time =time.time()print(f'Running time is {stop_time - start_time}....')return res #返回>>>>>>>>>>res<<<<<<<<<< (本例子中即download_movie的返回值)

returninner

download_movie=timer(download_movie)print(download_movie()) #>>> Aoi.avi

问题好像又解决了,然鹅,如果被装饰对象有参数,如:

#使用装饰器(被装饰对象有参数)

defdownload_movie(url):print(f'From {url}\nStart downloading........')

time.sleep(3)print(f'Download completed')如果还是 download_movie = timer(download_movie)

download_movie(url) >>>>>># 会报错,因为download实际上是inner的别名。调用的是inner(url)

于是修改装饰器:

deftimer(func):definner(url):

start_time=time.time()

func(url)#从闭包函数inner获取参数

stop_time =time.time()print(f'Running time is {stop_time - start_time}....')returninner

download_movie= timer(download_movie) #>>>>>返回inner >>>>>>更名为download_movie

download_movie('https://www.baidu.com/')

问题好像又解决了,然鹅,如果不确定被装饰对象的参数个数那又该怎么办呢?

修改装饰器,最终版本:

deftimer(func):def inner(*args, **kwargs):

start_time=time.time()

res= func(*args, **kwargs) #>>>>>>>>>>>用res接收func()产生的返回值<<<<<<<<<<<<<<<

stop_time =time.time()print(f'Running time is {stop_time - start_time}....')return res #返回>>>>>>>>>>res<<<<<<<<<< (本例子中即download_movie的返回值)

return inner

解决~~~~

欸,等下~~~~~~~~~~~这装饰器用起来还是有点麻烦啊

python大佬为我们提供了更简洁的装饰器调用方式。装饰器语法糖@

deftimer(func):def inner(*args, **kwargs):

start_time=time.time()

res= func(*args, **kwargs) #>>>>>>>>>>>用res接收func()产生的返回值<<<<<<<<<<<<<<<

stop_time =time.time()print(f'Running time is {stop_time - start_time}....')return res #返回>>>>>>>>>>res<<<<<<<<<< (本例子中即download_movie的返回值)

returninner

@timerdeffunc():print('hello world')#当我们调用func()时

func()#等价于 func = timer(func) func()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值