- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python无参装饰器的实现方案及优化由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
定义一个函数,该函数可为其他函数添加额外的功能.
需要在不修改被装饰对象源代码及其调用方式时,为被装饰对象添加额外的功能.
现在我们有如下一个函数help(),time.sleep()来模拟函数执行时间,print打印传入参数值,方便我们来进行分析。如果现在我们需要为help函数添加一个统计其运行时间的功能,我们可以怎么做?
1
2
3
4
5
6
7
|
import
time
def
help
(x, y):
time.sleep(
1
)
print
(f
'x={x} y={y}'
)
help
(
1
,
2
)
|
在help函数开头结束分别调用time.time(),两者相减得运行时间.
1
2
3
4
5
6
7
8
9
10
|
import
time
def
help
(x, y):
start
=
time.time()
time.sleep(
1
)
print
(f
'x={x} y={y}'
)
stop
=
time.time()
print
(stop
-
start)
help
(
1
,
2
)
|
运行结果:
方案一中我们在help中加了相关代码,虽然没有改变它的调用方式,但改变了它的源代码。我们继续想想如何两者都不改变的情况下,完成我们的目标.
对,函数内不能动,我们可以动函数外呀,在help前后加上相关代码,似乎就可以达到我们的目标了,这就是方案二,我们来试试.
1
2
3
4
5
6
7
8
9
10
|
import
time
def
help
(x, y):
time.sleep(
1
)
print
(f
'x={x} y={y}'
)
start
=
time.time()
help
(
1
,
2
)
stop
=
time.time()
print
(stop
-
start)
|
运行结果:
显而易见,似乎没有问题,但是如果我们需要多次调用help函数的话,在它前后都得加上相同的代码,这样代码就会显得十分冗余了。既然help函数前后代码不会变的话,我们可以将它们封装成另一个函数呀,说干就干.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
time
def
help
(x, y):
time.sleep(
1
)
print
(f
'x={x} y={y}'
)
def
wrapper():
start
=
time.time()
help
(
1
,
2
)
stop
=
time.time()
print
(stop
-
start)
wrapper()
|
运行一下:
。
这样我们就解决了多次调用的问题,但美中不足的是,help函数的调用方式改变了,而且help的参数固定,也只能修饰help函数,我们来一步步试着优化.
对参数优化,我们可以将help的实参通过wrapper的传入,而为了实现任意参数,我们首先想的便是*args,**kwargs来作为函数的参数,于是将方案三进行改进如下(为方便分析,为help多增加了一个参数):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import
time
def
help
(x, y, z):
time.sleep(
1
)
print
(f
'x={x} y={y} z={z}'
)
def
wrapper(
*
args,
*
*
kwargs):
start
=
time.time()
help
(
*
args,
*
*
kwargs)
stop
=
time.time()
print
(stop
-
start)
wrapper(
1
,
2
,
3
)
|
运行一下:
这样我们便将help的参数变得更加灵活了,接着我们来优化.
需要装饰其他对象,意味着我们在help位置的应该是一个可变参数,也就是用户输入的参数,即wapper函数内应变为:
1
2
3
4
5
|
def
wrapper(
*
args,
*
*
kwargs):
start
=
time.time()
func(
*
args,
*
*
kwargs)
stop
=
time.time()
print
(stop
-
start)
|
但是我们期望wrapper能和内部调用的func函数的参数一致,即wrapper的参数我们应该不去改变,那我们func的值从何处传来呢?
没错,我们可以运用闭包函数来传参,修改一下下:
1
2
3
4
5
6
7
8
|
def
outter(func):
def
wrapper(
*
args,
*
*
kwargs):
start
=
time.time()
func(
*
args,
*
*
kwargs)
stop
=
time.time()
print
(stop
-
start)
return
wrapper
|
这样我们为其他函数修饰时,只需要将其函数名作为outter函数的参数传入即可:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import
time
def
help
(x, y, z):
time.sleep(
1
)
print
(f
'这是help的{x}{y}{z}'
)
def
others(x, y, z):
time.sleep(
1
)
print
(f
'这是others的{x}{y}{z}'
)
def
outter(func):
def
wrapper(
*
args,
*
*
kwargs):
start
=
time.time()
func(
*
args,
*
*
kwargs)
stop
=
time.time()
print
(stop
-
start)
return
wrapper
help
=
outter(
help
)
others
=
outter(others)
help
(
1
,
2
,
3
)
others(
4
,
5
,
6
)
|
运行一下:
结果符合预期,而且在使用时由于outter内的func是在局部名称空间,outter外的func是在全局名称空间,调用时二者并不冲突,并且使用时可读性较高,我们好像达成开始的目标,似乎能以假乱真了。但我们继续思考一下,我们演示用到的函数十分简单,甚至没有返回值,如果加上返回值后,我们再对其修饰后,能得到原函数的返回值吗?
回到我们的wrapper中去,既然需要我们func函数的返回值,我们直接将其赋值给res,再return出res的值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import
time
def
help
(x, y, z):
time.sleep(
1
)
print
(f
'这是help的{x}{y}{z}'
)
return
'help'
def
others(x, y, z):
time.sleep(
1
)
print
(f
'这是others的{x}{y}{z}'
)
return
'others'
def
outter(func):
def
wrapper(
*
args,
*
*
kwargs):
start
=
time.time()
res
=
func(
*
args,
*
*
kwargs)
stop
=
time.time()
print
(stop
-
start)
return
res
return
wrapper
help
=
outter(
help
)
others
=
outter(others)
res1
=
help
(
1
,
2
,
3
)
res2
=
others(
4
,
5
,
6
)
print
(res1,res2)
|
没毛病,跑一下:
到这我们完成了一个简单的无参装饰器,装饰后的func既没有改变源代码,也没有改变调用方式.
但是代码稍显冗余,python语法便规定:在被装饰对象正上方单独一行写@装饰器名字,等价于func=outter(func),简化代码。从中我们总结出无参装饰器的一个模板:
1
2
3
4
5
6
7
8
9
10
11
12
|
def
outter(func):
def
wrapper(
*
args,
*
*
kwargs):
# 1、调用原函数
# 2、增加的新功能
res
=
func(
*
args,
*
*
kwargs)
return
res
return
wrapper
#使用时
@outter
def
func:
pass
|
到此这篇关于python无参装饰器的文章就介绍到这了,更多相关python无参装饰器内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/geter666/article/details/119706704 。
最后此篇关于Python无参装饰器的实现方案及优化的文章就讲到这里了,如果你想了解更多关于Python无参装饰器的实现方案及优化的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我应该编写一个函数来打印一组给定的三个数字中两个较大数字的平方和。 我对这种情况的处理相当笨拙。我没有编写返回一组 3 中最大的两个数字的函数,而是编写了函数,以便表达式减少到两个所需的数字。 # S
如果有人可以提供帮助,我将不胜感激。我一直在敲我的头一天试图让这个工作。我已经在互联网上搜索并重新阅读了手册,但我就是不明白。 guile << __EOF__ ( define heading-li
目前我正在处理一个方案问题,其中我们正在使用方案列表表示一个图。我们使用的第一个变体是表示为 的边列表图 '((x y) (y z) (x z)) 我们正在使用的图的第二个变体被称为 x 图,表示为
我正在尝试创建一个函数,该函数将两个函数作为参数并执行它们。 我尝试使用 cond ,但它只执行 action1 . (define seq-action (lambda (action1 act
我提前为我的原始英语道歉;我会尽量避免语法错误等。 两周前,我决定更新我对 Scheme(及其启示)的知识,同时实现我在手上获得的一些数学 Material ,特别是我注册的自动机理论和计算类(cla
Scheme中有没有函数支持分数的“div”操作? 意思是 - 11 格 2.75 = 4。 最佳答案 我认为你的问题的答案是:没有,但你可以定义它: #lang racket (define (di
我在scheme中实现合并排序,我必须通过定义两个辅助方法来实现:merge和split。 Merge 需要两个列表(已经按递增顺序)并将它们合并在一起。我这样做了如下: (define merge
尝试从终端加载方案文件。我创建了一个名为 test.scm 的文件,其中包含以下代码: (define (square x) (* x x)) (define (sum-of-squares x y)
我有以下代码: (define (howMany list) (if (null? list) 0 (+ 1 (howMany (cdr list))))) 如果我们执行以
我有点了解如何将基本函数(例如算术)转换为Scheme中的连续传递样式。 但如果函数涉及递归怎么办?例如, (define funname (lambda (arg0 arg1)
我正在尝试附加两个字符串列表 但我不知道如何在两个单词之间添加空格。 (define (string-concat lst1 lst2) (map string-append lst1
这个问题已经有答案了: How do I pass a list as a list of arguments in racket? (2 个回答) 已关闭 8 年前。 我有一个函数,它需要无限数量的
我对这段代码的工作方式感到困惑: (define m (list 1 2 3 '(5 8))) (let ((l (cdr m))) (set! l '(28 88))) ==>(1 2 3 (5 8
我正在为学校做一项计划作业,有一个问题涉及我们定义记录“类型”(作为列表实现)(代表音乐记录)。 我遇到的问题是我被要求创建一个过程来创建这些记录的列表,然后创建一个将记录添加到该列表的函数。这很简单
我有以下代码: (define (howMany list) (if (null? list) 0 (+ 1 (howMany (cdr list))))) 如果我们执行以
我正在尝试附加两个字符串列表 但我不知道如何在两个单词之间添加空格。 (define (string-concat lst1 lst2) (map string-append lst1
如何使用抽象列表函数(foldr、foldl、map 和 filter 编写函数),无需递归,消耗数字列表 (list a1 a2 a3 ...) 并产生交替和 a1 - a2 + a3 ...? 最
我试图找出在 Scheme 中发生的一些有趣的事情: (define last-pair (lambda (x) (if (null? (cdr x))
这个问题在这里已经有了答案: Count occurrence of element in a list in Scheme? (4 个答案) 关闭 8 年前。 我想实现一个函数来计算列表中元素出现
我正在尝试使用下面的代码获取方案中的导数。谁能告诉我哪里出错了?我已经尝试了一段时间了。 (define d3 (λ (e) (cond ((number? e) 0) ((e
我是一名优秀的程序员,十分优秀!