python--对于装饰器的理解

1、首先,有个原来写好的函数,完成一定的功能,比如下面的,就打印一句话(某程序被调用)。简单点,容易帮我们想清楚程序是怎么执行的。

1 ‘‘‘
2 原函数
3 ‘‘‘
4 def fun1():
5     print("fun1 is called.")
6
7 fun1()

结果:

2、然后,有个需求,要在原来的函数上加个功能,我们简单点,就再打印一句话吧(某新功能加入)。

2.1 不懂装饰器,就直白点吧,加一个fun2

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2():
 6     print("new fun is called")
 7
 8 ‘‘‘
 9 原函数
10 打印一句话(某程序被调用),
11 ‘‘‘
12 def fun1():
13     fun2()
14     print("fun1 is called.")
15
16 fun1()

结果:

这样子,结果是我们想要的,先执行新功能的程序,再执行原功能的程序,但是有个问题,原来的程序中加入了新的代码,示例中的13行。

写程序有个原则,叫封闭,就是原来跑得好好的代码不要再去改它,免得改来改去得再出问题。所以,我们得改。

2.2 不修改源代码,我们把原函数名字作为参数传给新功能的函数,先跑新功能,完了再掉用作为参数传进去的原功能

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2(funname):
 6     print("new fun is called")
 7     funname()
 8
 9 ‘‘‘
10 原函数
11 打印一句话(某程序被调用),
12 ‘‘‘
13 def fun1():
14     print("fun1 is called.")
15
16 fun2(fun1)

结果:

也是我们要的结果。然后新问题来了,这种方式,可不是原来直接调用fun1(),那么程序中所有用到fun1()的地方都得改成fun2(fun1),如果需要实现对就功能进行加强的地方很多,可以想象,你得找到所有的地方进行修改,程序大了,可不能这么干,万一漏了呢?我们还得改。

2.3 不改源代码,不改调用方式

把原来的程序在新程序中返回,然后再赋值给fun1,这样执行会是什么结果呢?

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2(funname):
 6     print("new fun is called")
 7     return funname
 8
 9 ‘‘‘
10 原函数
11 打印一句话(某程序被调用),
12 ‘‘‘
13 def fun1():
14     print("fun1 is called.")
15
16 fun1=fun2(fun1)
17
18 fun1()

结果:

在这个程序里,调用fun1()可以获得和原来一样的结果,但是,这里有个问题,“new fun is called”是在16行的时候,运行fun2时出来的,“fun1 is called”是在18行运行fun1时出来的,也就是说这个程序实际上并没有将fun1和fun2关联起来,它并没有在fun1()调用的时候同时实现新旧两个功能,它和以下代码是一样的

1 def fun2():
2     print("new fun is called")
3     return
4 def fun1():
5     print("fun1 is called.")
6 fun2()
7 fun1()

这就没有装饰的意思了
2.4 不改源代码,不改调用方式,一次调用执行实现新旧两个功能

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2(funname):
 6     def inner():
 7         print("new fun is called")
 8         funname()
 9     return inner
10
11 ‘‘‘
12 原函数
13 打印一句话(某程序被调用),
14 ‘‘‘
15 def fun1():
16     print("fun1 is called.")
17
18
19 fun1=fun2(fun1)
20
21 fun1()

在这个代码里,fun1作为参数传给fun2,在fun2中定义了一个函数,在这个嵌套定义的函数中实现了新功能,那么fun2干嘛呢?它只是将这个新功能的地址作为返回值返回。我们拿到这个返回值,重新赋值给fun1,那么再调用fun1的时候,实际上是调用的fun2中定义的新功能函数。
结果:

我们可以通过debug运行,给每行打上断点,就能知道最终的结果是在运行到21行的时候一起出来的。

2.5 在以上基础上,可以看到旧功能是在fun1中实现的,新功能是在fun2中实现的,调用的还是fun1,多了一句话,即19行,传参+复制,会不会搞不清楚,于是,简写一下

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2(funname):
 6     def inner():
 7         print("new fun is called")
 8         funname()
 9     return inner
10
11 ‘‘‘
12 原函数
13 打印一句话(某程序被调用),
14 ‘‘‘
15 @fun2
16 def fun1():
17     print("fun1 is called.")
18
19 fun1()

将@fun2写在fun1之前,就表示fun2写了新功能,它是在fun1的基础上来的,把fun1妆点了一下门面,有点加强了--装饰器这个名字很贴切的。

2.6 函数的定义是为了重复调用,可以少写代码,现在我们有fun2(新功能),可以想象,可能有很多其他的fun**(旧功能)需要妆点,如果原来的fun**本身带参数,那么就会报错。

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2(funname):
 6     def inner():
 7         print("new fun is called")
 8         funname()
 9     return inner
10
11 ‘‘‘
12 原函数
13 打印一句话(某程序被调用),
14 ‘‘‘
15 @fun2
16 def fun1():
17     print("fun1 is called.")
18
19 @fun2
20 def fun3(arg1):
21     print("fun3 welcome: %s "%arg1)
22
23 fun1()
24 fun3("susen")

结果:

所以,我们需要用非固定参数来解决这个问题。在装饰器的inner函数用非固定参数*args,**kwargs,这样,不管原来的函数有多少参数,都可以调用了。

 1 ‘‘‘
 2 在原来的函数上加个功能
 3 再打印一句话吧(某新功能加入)。
 4 ‘‘‘
 5 def fun2(funname):
 6     def inner(*args,**kwargs):
 7         print("new fun is called")
 8         funname(*args,**kwargs)
 9     return inner
10
11 ‘‘‘
12 原函数
13 打印一句话(某程序被调用),
14 ‘‘‘
15 @fun2
16 def fun1():
17     print("fun1 is called.")
18
19 @fun2
20 def fun3(arg1):
21     print("fun3 welcome: %s "%arg1)
22
23 fun1()
24 fun3("susen")

结果:

3、总结

按照上面一步步得来,应该能明白装饰器是怎么工作的了,基础知识有:非固定参数传参、函数名实际上也是一个变量(内存地址)、嵌套函数。明白以后,之后写代码就套用格式就完了。

时间: 2024-11-05 18:37:01

python--对于装饰器的理解的相关文章

python二重装饰器初步理解

def first(f): print f.__name__,'call first()' def fn_1(): print f.__name__,'call first()_ fn_1()' return f() return fn_1 def second(f): print f.__name__,'call second()' def fn_2(): print f.__name__,'call second()_fn_2()' return f() return fn_2 def te

[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考

最近写一个py脚本来整理电脑中的文档,其中需要检校输入的字符,为了不使代码冗长,想到使用装饰器. 上网搜索有关python的装饰器学习文档,主要看的是AstralWind的一篇博文,以及Limodou的一篇文章.作为初学者,这两篇文章对新手有很大的帮助,但仍然有些不易理解的地方.因此在此以一个初学者的认知记录一下python的装饰器的学习心得. 1. 什么是装饰器? 顾名思义,装饰器就是在方法上方标一个带有@符号的方法名,以此来对被装饰的方法进行点缀改造. 当你明白什么是装饰器之后,自然会觉得这

转发对python装饰器的理解

[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考 原文  http://blog.csdn.net/sxw3718401/article/details/39519587 主题 Python 最近写一个py脚本来整理电脑中的文档,其中需要检校输入的字符,为了不使代码冗长,想到使用装饰器. 上网搜索有关python的装饰器学习文档,主要看的是 AstralWind的一篇博文,以及Limodou的一篇文章.作为初学者,这两篇文章对新手有很大的帮助,但仍然有些不易理解的地方

python之我对装饰器的理解

从一开始学习python的时候,就一直不是很理解装饰器是个什么东东,再看了很多篇博文和自己动手敲了好多代码后,算是略有了解. 我理解的装饰器是: 在不改变原有函数调用的情况下,对其进行包装,使其变成另外一种函数来使用,一般的用途是 插入日志.性能测试.事务处理等. def host_restrict(tags=[], names=[]):     def decorator(f):         @functools.wraps(f)         def decorated(*args, 

python入门基础-函数装饰器的理解

1.装饰器 # 知乎某大神是这么比喻装饰器的:内裤可以用来遮羞,但是到了冬天他就没有办法为我们御寒,聪明的人于是发明了长裤,有了长裤后宝宝再也不冷了, # 装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效. # # 大神是将程序中原本的函数比喻成内裤,而装饰器比喻成了长裤,这样在寒冬里它们结合一起使用就给所有人带来了温暖. # # 装饰器本质上是一个python函数,它可以让其它函数在不改动代码的情况下增加额外的功能,并且装饰器的返回值也是一个函数对象. # 在

python入门(六)装饰器的理解

装饰器用于拓展原有函数功能的一种函数比如: def helloWorld(fun) def out() print ("======start========") fun() print ("=====end======") return out @helloWorld def back () print ("let's go") back() 运行结果: ======start======== let's go =====end====== b

皇帝的新衣(python装饰器的理解和使用)

今天来说说装饰器. 在python语言中,装饰器的主要作用是减少重复输入的精髓.有了装饰器,可以非常直观而优雅的使用重复代码,就像一件衣服,可以给皇帝穿,也可以给任何人穿,只要你觉得需要这件“衣服” 语法: @装饰函数名    如@yifu  就是一个装饰器,yifu就是一个装饰函数 好吧,我们先来做一件衣服(装饰函数): def yifu(func):     #yifu是装饰函数名,func是皇帝(被装饰的函数),合起来就叫:皇帝的新衣 def gongneng(): print(“我是一个

python函数装饰器

学习装饰器前提需要了解高阶函数,函数嵌套,函数闭包 python函数装饰器,顾名思义就是装饰函数,为函数添加新功能的的一种方式. 为什么要使用装饰器呢? 因为函数在运行时,如果不使用装饰器对函数进行功能添加,需要修改函数源代码,这样修改无疑会增加程序的冗余和复杂性,也不便于程序员对其进行修改.使用装饰器,可以在不改变函数源代码和调用方式的前提下,使用语法糖@装饰器,对函数功能进行添加. 装饰器本质上就是一个函数. 我们使用一个简单的例子来实现: import time #这是一个装饰器函数名为t

Python之装饰器、迭代器和生成器

在学习python的时候,三大“名器”对没有其他语言编程经验的人来说,应该算是一个小难点,本次博客就博主自己对装饰器.迭代器和生成器理解进行解释. 为什么要使用装饰器 什么是装饰器?“装饰”从字面意思来谁就是对特定的建筑物内按照一定的思路和风格进行美化的一种行为,所谓“器”就是工具,对于python来说装饰器就是能够在不修改原始的代码情况下给其添加新的功能,比如一款软件上线之后,我们需要在不修改源代码和不修改被调用的方式的情况下还能为期添加新的功能,在python种就可以用装饰器来实现,同样在写

【转】详解Python的装饰器

原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def say_hello(): print "hello!" def say_goodbye(): print "hello!" # bug here if __name__ == '__main__':