Decorators(装饰器)初级

编辑:光环大数据 来源: 互联网 时间: 2017-10-31 14:41 阅读:

  Decorators(装饰器)初级.Decorators提供了一种简单的句法来实现运行更高级的函数(higher-orderfunctions).根据定义,decorator是一种函数,它可以应用其他函数并拓展其行为而不用对函数进行明确地修改。听起来有些令人困惑,但是事实上它并不复杂,特别是当我们研究完下面几个例子后。

在这个介绍性教程中,我们会看到什么是decorators和如何去创建并应用它。

首先,最重要的是在你能够理解decorators之前,你必须先理解...函数是如何工作的.最基本且最重要的,函数会根据传入的数据返回一个值。

deffoo(bar):

returnbar+1

printfoo(2)==3

第一类对象(FirstClassObjects)

在python中,函数是第一类对象(first-classobjects)。这意味着函数可以被传递,像参数一样被使用,就像其他的类型(例如:string,int,float)一样。

deffoo(bar):

returnbar+1

printfoo

printfoo(2)

printtype(foo)

defcall_foo_with_arg(foo,arg):

returnfoo(arg)

printcall_foo_with_arg(foo,3)

内嵌函数(NestedFunctions)

由于在Python里函数优先的性质,你可以在其他函数里定义一个新函数。这类的函数被称作内嵌函数。

defparent():

print"Printingfromtheparent()function."

deffirst_child():

return"Printingfromthefirst_child()function."

defsecond_child():

return"Printingfromthesecond_child()function."

printfirst_child()

printsecond_child()

当你调用parent()的时候会发生什么呢?请先想一会儿。你应该会得到……

Printingfromtheparent()function.

Printingfromthefirst_child()function.

Printingfromthesecond_child()function

尝试去调用first_child()一下。你应该会得到一个错误:

Traceback(mostrecentcalllast):

File"decorator3.py",line15,in<module>

first_child()

NameError:name'first_child'isnotdefined

我们了解到了什么?

不论你什么时候调用parent(),子函数first_child()和second_child()也都被调用,并且,因为作用域的缘故,这两个子函数在母函数之外都是不可用的(例如不可以被调用)。

返回函数(ReturningFunctions)

Python也允许你在函数中返回其他函数的函数值。让我们改变一下之前的函数作为这个的例子。

defparent(num):

deffirst_child():

return"Printingfromthefirst_child()function."

defsecond_child():

return"Printingfromthesecond_child()function."

try:

assertnum==10

returnfirst_child

exceptAssertionError:

returnsecond_child

foo=parent(10)

bar=parent(11)

printfoo

printbar

printfoo()

printbar()

前两个输出的结果是:

<functionfirst_childat0x1004a8c08>

<functionsecond_childat0x1004a8cf8>

这简单地说明了foo对应着first_child()函数,bar对应着second_child()函数。

后两个函数结果的输出证明了这一点。

Printingfromthefirst_child()function.

Printingfromthesecond_child()function.

最后,你有没有注意到在第三个例子中,我们在母函数中执行了子函数,例如:second_child()。同时,在最后一个例子中,当我们调用子函数first_child时,我们没有在其中添加插入成分,以便我们在将来可以调用它。清楚了吗?

现在,我的朋友,你已经做好准备来学习decorators了!

让我们来看两个例子…

第一个例子:

defmy_decorator(some_function):

defwrapper():

print"Somethingishappeningbeforesome_function()iscalled."

some_function()

print"Somethingishappeningaftersome_function()iscalled."

returnwrapper

defjust_some_function():

print"Wheee!"

just_some_function=my_decorator(just_some_function)

just_some_function()

你能猜一下输出结果会是什么吗?试一试。

Somethingishappeningbeforesome_function()iscalled.

Wheee!

Somethingishappeningaftersome_function()iscalled.

想要理解这里发生了什么,你只需要回去看看前四个例子。我们差不多只运用了所有已经学过了的东西。简单地说,decorators包装了一个函数,然后修改了它的行为(功能)。

让我们再进一步,增加一个if语句。

第二个例子:

defmy_decorator(some_function):

defwrapper():

num=10

ifnum==10:

print"Yes!"

else:

print"No!"

some_function()

print"Somethingishappeningaftersome_function()iscalled."

returnwrapper

defjust_some_function():

print"Wheee!"

just_some_function=my_decorator(just_some_function)

just_some_function()

这将输出:

Yes!

Wheee!

Somethingishappeningaftersome_function()iscalled.

是时候来一点语法糖(syntacticsugar)了!

Python允许你运用@标志来简化decorators的调用(这叫做“pie”句法)

让我们为我们的decorator创建一个模块:

fromdecorator7importmy_decorator

@my_decorator

defjust_some_function():

print"Wheee!"

just_some_function()

当你运行这个例子时,你应该会得到与之前的相同的输出结果:

Yes!

Wheee!

Somethingishappeningaftersome_function()iscalled.

所以,@my_decorator只是just_some_function=my_decorator(just_some_function).的一个更简单的表示方式。

现实世界

来看些关于现实生活的例子……

importtime

deftiming_function(some_function):

"""

Outputsthetimeafunctiontakes

toexecute.

"""

defwrapper():

t1=time.time()

some_function()

t2=time.time()

return"Timeittooktorunthefunction:"+str((t2-t1))+"\n"

returnwrapper

@timing_function

defmy_function():

num_list=[]

forxin(range(0,10000)):

num_list.append(x)

print"\nSumofallthenumbers:"+str((sum(num_list)))

printmy_function()

这个程序在你运行my_function()会返回刚开始运行的时间点和运行后的时间点。之后,我们只要简单的减去这两个数便可以知道这个函数到运行了多久。

运行一下程序。一行一行的输入,完成它。确保你知道这个程序如何工作。

fromtimeimportsleep

defsleep_decorator(function):

"""

Limitshowfastthefunctionis

called.

"""

defwrapper(*args,**kwargs):

sleep(2)

returnfunction(*args,**kwargs)

returnwrapper

@sleep_decorator

defprint_number(num):

returnnum

printprint_number(222)

forxinrange(1,6):

printprint_number(x)

这个decorator是用来限定速率的。请自己测试一下。

最后,一个在Python里最常被用到的decorators是login_required()。它可以用来确保一名使用者在他/她进入一个特殊通道之前可以登录或者进行正确的身份验证。(如这个例子里的/secret)

fromfunctoolsimportwraps

fromflaskimportg,request,redirect,url_for

deflogin_required(f):

@wraps(f)

defdecorated_function(*args,**kwargs):

ifg.userisNone:

returnredirect(url_for('login',next=request.url))

returnf(*args,**kwargs)

returndecorated_function

@app.route('/secret')

@login_required

defsecret():

Pass

你注意到函数被传递给decorator:functools.wraps()了么。这简单地保存了(preserves)封装函数的元数据。

 

  Python培训Python培训班Python培训机构,就选光环大数据!

  还不够过瘾?想学习更多?点击 http://hadoop.aura.cn/python/ 进行Python学习!


大数据培训、人工智能培训、Python培训、大数据培训机构、大数据培训班、数据分析培训、大数据可视化培训,就选光环大数据!光环大数据,聘请专业的大数据领域知名讲师,确保教学的整体质量与教学水准。讲师团及时掌握时代潮流技术,将前沿技能融入教学中,确保学生所学知识顺应时代所需。通过深入浅出、通俗易懂的教学方式,指导学生更快的掌握技能知识,成就上万个高薪就业学子。 更多问题咨询,欢迎点击------>>>>在线客服

你可能也喜欢这些

在线客服咨询

领取资料

X
立即免费领取

请准确填写您的信息

点击领取
#第三方统计代码(模版变量) '); })();
'); })();