1.情景引入。
现在已经完成了一个python项目,但是我们为了安全起见,我们需要加入验证机制。不是所有人都能调用函数
原始源代码
def f1():
print 'f1'
def f2():
print 'f2'
def f3():
print 'f3'
由于必须遵循开发闭包的原则,所以我们应该尽可能的是不去改动原来函数的内部代码,而是通过其他的一些方法添加新的功能
比如通过下面这样的方法
#首先定义一个验证函数,参数为一个函数
def verification(func):
print("verification success!!!")
return func #返回传入函数的首地址
def f1():
print 'f1'
def f2():
print 'f2'
def f3():
print 'f3'
f1=verification(f1)
#执行这一句代码后,会直接输出"verification success!!!",因为我们执行了verification这个函数。然后返回传入函数的地址
#再执行返回的函数,这样就会执行f1()这个函数
f1()
#最终结果
"""
verification success
f1
"""
换一种写法,实现和上面同样的功能——–装饰器
def verification(func):
print("verification success!!!")
return func #返回传入函数的首地址
@verification
def f1():
print 'f1'
@verification跟上一段代码的f1=verification(f1)这条语句等价,此时的f1已经是verification函数的返回值了,即func
上面的代码不经过任何调用直接运行
结果:
verification success!!!
加一条代码
f1=f1() #相当于f1=func(),func是verification返回的函数,即原f1()函数
结果:
verification success
f1
由此我们发现了一个问题,那就是我们直接使用@verification的时候他是直接执行了verification这个函数,因此他会先有输出”verification success“,这就出现了不统一的问题,按照我们原来的设想是”verification success“和”f1“应该同时输出的。因此我们用相同的原理,写一个内部函数,通过返回内部函数的地址,达到不执行函数的效果
代码如下:
def verification(func):
def inner():
print "verification success"
func()
return inner #返回了一个函数的地址,没有直接执行
@verification
def f3():
print 'f3'
此时函数f3已经变成了inner了,然后我们调用f3,即inner
f3() #这里就直接执行了inner函数
输出结果
verification success
f1
实现(原函数无返回值)
def verification(func):
def inner(arg):
if arg>100:
func(arg)
else:
print "verification fail"
return inner
@verification
def f1(num):
print num
@verification
def f2(num):
print num
f1(101)
f2(88)
结果:
101
verification fail
原函数有返回值
def verification(func):
def inner(arg):
if arg>100:
return func(arg)
else:
return "verification fail"
return inner
@verification
def f1(num):
return "data is %d"%num
@verification
def f2(num):
return "data is %d" % num
print f1(101)
print f2(88)
结果:
data is 101
verification fail
多参数传递
"验证功能的函数"
def verification(func):
def inner(*args,**kargs):
if 'password' in kargs:
password=kargs['password']
else:
password='000'
if password=='233':
return func(*args)
else:
return "verification fail"
return inner
@verification
def f1(num):
return "data is %d"%(num)
@verification
def f2(num):
return "data is %d" % num
print f1(101,password='233') #此时的f1其是inner函数
print f2(88)
#结果:
data is 101
verification fail
2.装饰器
就如同以上代码一样,想要对一个已有的模块做一些“修饰工作”,所谓修饰工作就是想给现有的模块加上一些小装饰(一些小功能,这些小功能可能好多模块都会用到),但又不让这个小装饰(小功能)侵入到原有的模块中的代码里去。
3.进阶版—-带参数Decrorator
def makeHtml(tag,*args,**kwargs):
def realDeco(main_fun):
if 'css_class' in kwargs:
css_class="class={}".format(kwargs['css_class'])
else:
css_class=None
def wrapper(*args,**kwargs):
return "<"+tag+" "+css_class+">"+main_fun(*args,**kwargs)+"</"+tag+">"
return wrapper
return realDeco
@makeHtml(tag="b",css_class="bold_css")
def index():
return 'hello world'
print index()
执行过程
到@makeHtml时,程序执行过程
1.先执行makeHtml(tag=’b’,class=’bold_css’)函数,返回realDeco的地址
2.执行realDeco(index),获取到css_class变量的值,返回wrapper
3.执行print index().此时此刻的index=wrapper,执行wrapper()函数,
4.执行main_fun(即原index函数),重新拼接得到<b class=bold_css>hello world</b>
,最后返回了这个值
执行结果:
<b class=bold_css>hello world</b>
待续。。。。