python:装饰器

本文介绍了Python装饰器的概念,从情景引入出发,讨论了如何在不改变原函数代码的情况下添加新功能。通过实例展示了装饰器如何处理无返回值、有返回值及多参数传递的情况。并进一步探讨了带参数的装饰器的工作原理,详细解释了执行过程。
摘要由CSDN通过智能技术生成

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>

待续。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值