python decorator. decorator_浅析python中的装饰器decorator

最近学习python,其中decorator比较难理解,遂写一篇来总结供后续查阅。

定义一个函数,想在运行时动态的改变函数的功能,又不想改变函数本身的代码,可以使用高阶函数(可以使用函数作为参数)

装饰器函数可以简化代码,避免每个函数编写重复的代码,也可以用在python web开发中进行登录限制。

1,一般的函数调用-硬编码调用,代码中直接调用函数(直接调用原函数):

deffunc1():print ("func1")deffunc2():print("before")

func1()print("after")

func2()

输出为:

2,python中可将函数作为参数进行传递(高阶函数):

deffunc1():print("func1")defwrapper(func): #装饰器函数print("before")

func()print("after")return func #如果不写return func,函数会自动返回,默认为0

func1=wrapper(func1)

调用结果同上。

wrapper函数最后如果不返回func,再次调用func1,则会包以下错误TypeError: 'NoneType' object is not callable:

3,python中的decorator中可以简化上述调用:

defwrapper(func):print("before")

func()print("after")returnfunc

@wrapperdeffunc1():print("func1")

直接执行,结果同上。

4,这种装饰器执行一次调用一次,我们如果希望显示调用,则可以在函数内部封装一层:

defwrapper(func):definner():print("before")

func()print("after")returninner

@wrapperdeff():print("call f")

f()#显示调用

5,上面是无参数的装饰器,python中可以实现有参装饰器调用:

defwrapper(func):definner(a,b):print("before wrapper")

func(a,b)print("after wrapper")returninner

@wrapperdeff(a,b):print ("call f: a+b=%d"% (a+b) )

f(2,3) #f=wrapper(f)=inner

6,有时候,不确定装饰器中参数个数的情况下,就不能使用一般参数、默认参数了,可以使用(*args, **kwargs)来自动适应变参和命名参数:

#coding:utf-8

defwrapper(func):def inner(*args, **kwargs):print("before %s"%func.__name__)

result=func(*args,**kwargs)print("result of %s is %d"%(func.__name__,result))returninner

@wrapperdeff1(a,b):print("call f1")return a+b

@wrapperdeff2(a,b,c):print("call f2")return a+b+c

f1(1,2)

f2(2,3,4)

7,使用functools.wraps在装饰器中包裹传进来的函数,这样就不会丢失传进来的函数的__name__等属性:

from functools importwrapsdefmy_decorator(func):

@wraps(func)def wrapper(*args, **kwargs):print('wrapper')

func(*args, **kwargs)returnwrapper

@my_decoratordefmy_fun():print('test')#exec

my_fun()

8,装饰器在flask中的应用:

#只贴出装饰器核心代码

deflogin_decorator(func):

@wraps(func)def wrapper(*args, **kwargs):if session.get('manage_name'):return func(*args, **kwargs)else:returnredirect(url_for('login'))returnwrapper

@app.route('/post')

@login_decoratordefpost():if request.method == 'GET':return render_template('post.html')else:pass

具体代码可见我的github

参考:简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值