首页>新闻>武汉有好的Python在线培训机构吗

武汉有好的Python在线培训机构吗

来源:达内IT教育-武汉校区

时间:2020/2/23 15:29:12

装饰器是可调用的对象,其参数是另一个函数(被装饰的函数)。Python的装饰器有函数装饰器和类装饰器,这篇文章谈谈Python的函数装饰器。


函数装饰器的基础知识

函数装饰器用于在代码中「标记」函数,以某种方式增强函数的行为。例如一个名为decorator的装饰器:

decorator

def sayHi():

print('Say hi~')

以上代码与下述写法一样:

def sayHi():

print('Say hi~')

sayHi=decorator(sayHi)

并且这两种写法的效果一样:上述代码执行完毕后所得到的sayHi不一定是原来的sayHi函数,而是decorator(sayHi)返回的函数。

实际上,装饰器只是Python的语法糖。前面的例子表明,装饰器可以像常规的可调用对象一样调用,其参数是另一个函数。因此,装饰器的两个特点是:一把被装饰的函数替换成其他的函数,二是装饰器在加载模块时就立即执行。

registry=[]

def register(func):

print('running register(%s)'%func)

registry.append(func)

return func

register

def f1():

print('running f1()')

register

def f2():

print('running f2()')

def f3():

print('running f3()')

if __name__=='__main__':

print('running registry-->',registry)

f1()

f2()

f3()

执行上述代码得到的输出如下:

$python deco.py

running register(<function f1 at 0x1039afcf8>)

running register(<function f2 at 0x1039b5398>)

('running registry-->',[<function f1 at 0x1039afcf8>,<function f2 at 0x1039b5398>])

running f1()

running f2()

running f3()

可以看到deco.py在执行main函数之前,运行了f1()函数和f2()函数。继续验证,导入deco.py,输出如下:

>>>import deco

running register(<function f1 at 0x10392dc8b>)

running register(<function f2 at 0x10392de2a>)

查看registry的值:

>>>deco.registry

[<function f1 at 0x10392dc8b>),<function f2 at 0x10392de2a>]

看到这里你应该能明白了,函数装饰器在导入模块时是立即执行的,而被装饰的函数只在明确调用时运行。

接下来举例函数装饰器的应用。

函数装饰器的应用

现在需求是将原来代码中的sayHi函数执行之前输出当前的时间。

import datetimedef print_now(func):

def decorate():

now=datetime.datetime.now()

func_name=func.__name__

print('<%s(%s)>'%(str(now),func_name))

func()

return decorate

print_now

def sayHi():

print('say Hi~')

然后调用sayHi函数,就能看到每次输出“say Hi~”之前的装饰器里定义的输出了。这种方式避免了改动原来的代码,对于不熟悉原来的代码逻辑的程序员来说是一种很好的修改办法。然而,装饰器也有缺陷,它替换了被装饰的函数,也遮盖了被装饰的函数的__name__、__doc__和__modual__属性。

我们接着查看sayHi函数的__name__属性:

>>>sayHi.__name__

'decorate'

为什么加了print_now这个装饰器的sayHi函数的__name__属性从“sayHi”变成了“decorate”?前面说了,装饰器遮盖了被装饰的函数的__name__、__doc__和__modual__属性。通过使用Python内置的functools.wraps装饰器可以把相关属性从sayHi函数复制到print_now装饰器里。

import functoolsimport datetime

def print_now(func):functools.wraps(func)

def decorate():

now=datetime.datetime.now()

func_name=func.__name__

print('<%s(%s)>'%(str(now),func_name))

func()

return decorate

print_now

def sayHi():

print('say Hi~')

执行上述代码:

>>>sayHi()

2017-12-20 21:25:18.045965(sayHi)

say Hi~

>>>sayHi.__name__

'sayHi'

可以看到sayHi函数的__name__属性恢复正常。

那么,如果被装饰的函数带参数,该如何定义装饰器呢?将sayHi函数加上一个name参数:

def sayHi(name):

print('say Hi~',name)

那么print_now装饰器的定义如下:

import functools

import datetime

def print_now(func):

functools.wraps(func)

def decorate(arg):

now=datetime.datetime.now()

func_name=func.__name__

print('<%s(%s)>'%(str(now),func_name))func(arg)

return decorate

print_now

def sayHi(name):

print('say Hi~%s'%name)

上述代码只是在print_now装饰器里的decorate函数传递了sayHi函数的参数,执行上述代码:

>>>sayHi('Eva')

2017-12-20 21:46:48.521607(sayHi)

say Hi~Eva

重叠装饰器

重叠装饰器就是对被装饰的函数同时使用多个装饰器。

例如,有装饰器d1、d2、d3,按顺序把这三个装饰器应用于func函数:

d1

d2

d3

def func():

pass

在上面的代码中,d2应用于d3返回的函数上,d1应用于d2返回的函数上。

上述代码于下述代码的效果一样:

def func():

pass

func=d1(d2(d3(func)))

参数化装饰器

参数化装饰器就是装饰器函数也带参数,如print_now(to_prt=True)。现在,给print_now装饰器加上to_prt参数,当to_prt参数值为True时,在sayHi函数执行之前输出当前的时间;当to_prt参数值为False时,则不输出当前的时间。

import functools

import datetime

def print_now(to_prt=True):def to_prt_decorator(func):

functools.wraps(func)

def decorate(arg):if to_prt:

now=datetime.datetime.now()

func_name=func.__name__

print('<%s(%s)>'%(str(now),func_name))

func(arg)

return decorate return to_prt_decorator print_now(to_prt=False)

def sayHi(name):

print('say Hi~%s'%name)

上述代码中的print_now装饰器又增加了一层嵌套,并且使用装饰器的to_prt参数在sayHi函数执行之前来判断是否输出当前的时间。执行上述代码:

>>>sayHi('Eva')

say Hi~Eva

可以看到没有打印当前的时间了。

实际上,Python是把被装饰的函数作为个参数传给装饰器函数来实现参数化装饰器的。如果不使用装饰器的语法,则调用sayHi函数的方法如下:

sayHi=print_now(to_prt=True)(sayHi)

>>>sayHi('Eva')

<2017-12-20 22:16:39.494790(sayHi)>

say Hi~Eva

以上就是小编讲的大致内容了,还有什么相关问题要问的,达内IT教育涵盖基本行业知识,安排的合理,专业师资,小班授课,费用低,学习快,400咨询热线24小时答疑。


  • 上一篇:武汉有好的Python线上培训吗
  • 下一篇:武汉有好的UI设计在线培训班吗
  • 相关推荐 更多>

    武汉当下热度很高的Java培训机...

    武汉有经验的Java培训机构名单...

    武汉本土实力强的Java培训机构...

    武汉目前大热的Java培训机构精...

    武汉精选好的Java培训机构...

    武汉时下出名的Java培训机构今...

    预约体验课

    版权所有:搜学搜课(www.soxsok.com)

  • 在线咨询
  • 电话咨询
  • 预约试听

  • ;