js9905com金沙网站python的装饰器

python的装饰器

鉴于函数也是二个对象,而且函数作为三个破例的指标足以被赋值给任何变量(value

pringname(卡塔尔国),相反,通过变量也是足以调用函数的,以下是一个简便的事例:

 

 

1 >>> def printName():

2 ... print("My name is Jobs")

3 ... 

4 >>> name = printName

5 >>> 

6 >>> printName()

7 My name is Jobs

8 >>> name()

9 My name is Jobs

 

 

 

由上述代码大家轻便看出,printName(卡塔尔国函数被赋值给name变量,相符用name变量也能够调用printName(卡塔尔国函数。那个时候他俩是如出生机勃勃辙的,在那处说一点小知识:函数对象有

 

一个__name__品质,能够得到函数的名字:

 

例子:

 

 

1 >>> 

2 >>> name.__name__

3 'printName'

4 >>> printName.__name__

5 'printName'

 

现行,如果大家要增长printName函数的作用,举例,在函数调用前后自动打字与印刷日志,但又不希望修正printName函数的概念,这种在代码运营时期动态增添效果的法子,称之为“

 

装饰器”(Decorator)。本质上,decorator便是二个回来函数的高阶函数。所以,大家要定义一个能打字与印刷日志的decorator,可以定义如下:

 

例子一:

 

 

 

1 >>> 

2 >>> def log(func):

3 ... def wrapper(*args,**kw):

4 ... print 'call %s()' %func.__name__

5 ... return func(*args,**kw)

js9905com金沙网站,6 ... return wrapper

7 ...

 

 

 

 

观测地方的log,因为它是贰个decorator,所以接纳二个函数作为参数,并回到贰个函数。大家要凭仗Python的@语法,把decorator置于函数的定义处:

 

 

1 >>> @log

2 ... def printName():

3 ... print("My name is Jobs")

4 ... 

5 >>> printName()

6 call printName()

7 My name is Jobs

 

例子二:

 

 

 1 >>> 

 2 >>> @log

 3 ... def printAge():

 4 ... print '%s,my age is 120' %printName() 

 5 ... 

 6 >>> job = printAge()

 7 call printAge()

 8 call printName()

 9 My name is Jobs

10 None,my age is 120

 

 

 

当你调用printName可能printAge(State of Qatar时,不仅仅会调用函数本身,何况会调用在调用该函数早前打字与印刷一些日志。把@log放在printAge(State of Qatar函数在此之前一定于实践了语句:

 

name= log(printName)

 

鉴于log(卡塔尔是二个decorator,重回一个函数,所以,原本的now(卡塔尔函数照旧存在,只是以后同名的printName(卡塔尔国了新的函数,于是调用printName(卡塔尔(قطر‎将实施新函数,即在log(State of Qatar函数中回到的wrapper(卡塔尔(قطر‎函数。

 

wrapper(卡塔尔函数的参数定义是(*args, **kw卡塔尔国,由此,wrapper(卡塔尔国函数能够承担负意参数的调用。在wrapper(卡塔尔函数内,首先打字与印刷日志,再接着调用原始函数。

 

假设decorator本身需求传入参数,那就需求编写制定三个回来decorator的高阶函数,写出来会更复杂。举例,要自定义log的文书:

 

 

1 def log(text):

2     def decorator(func):

3         def wrapper(*args, **kw):

4             print '%s %s():' % (text, func.__name__)

5             return func(*args, **kw)

6         return wrapper

7     return decorator

 

这个3层嵌套

 

 

 1 >>> def log(text):

 2 ...     def decorator(func):

 3 ...         def wrapper(*args,**kw):

 4 ...             print '%s %s():' %(text,func.__name__)

 5 ...             return func(*args,**kw)

 6 ...         return wrapper

 7 ...     return decorator

 8 ... 

 9 >>> @log('excute')

10 ... def printName():

11 ...     print("My name is Jobs!")

12 ... 

13 >>> printName()

14 excute printName():

15 My name is Jobs!

16 >>> 

 

我们来解析上面的言辞,首先实行log('execute'卡塔尔国,再次回到的是decorator函数,再调用重回的函数,参数是now函数,再次来到值最后是wrapper函数。

 

如上二种decorator的概念都并没不符合规律,但还差最后一步。因为我们讲了函数也是目的,它有__name__等本性,但您去看经过decorator装饰之后的函数,它们的__name__业已从原来的'printName产生了'wrapper':

 

>>> printName.__name__

'wrapper'

>>> 

因为重临的不胜wrapper(卡塔尔国函数名字便是'wrapper',所以,需求把原始函数的__name__等品质复制到wrapper(卡塔尔(قطر‎函数中,不然,有些信任函数具名的代码实施就能够出错。

 

不要求编写制定wrapper.__name__ = func.__name__那样的代码,Python内置的functools.wraps正是干这一个事的,所以,多个完完全全的decorator的写法如下:

 

 

1 >>> def log(func):

2 ...     @functools.wraps(func)

3 ...     def wrapper(*args,**kw):

4 ...         print 'call %s():' %func.__name__

5 ...         return func(*args,**kw)

6 ...     return wrapper

7 ... 

8 >>> 

 

也足以本着呆参数的decorator:

 

 

import functools

 

def log(text):

    def decorator(func):

        @functools.wraps(func)

        def wrapper(*args, **kw):

            print '%s %s():' % (text, func.__name__)

            return func(*args, **kw)

        return wrapper

    return decorator

 

 

 

这是二个翻新的例证,希望协助咱们知晓:

 

 1 >>> def deco(func):

 2 ...     def _deco(a,b):

 3 ...         print ("before myfunc() called.")

 4 ...         ret = func(a,b)

 5 ...         print("after called.result:%s" %ret)

 6 ...         return ret

 7 ...     return _deco

 8 ... 

 9 

10 >>> @deco

11 ... def myfunc(a,b):

12 ...     print("myfunc(%s,%s) called."%(a,b))

13 ...     return a+b

14 ... 

15 >>> myfunc(1,2)

16 before myfunc() called.  

17 myfunc(1,2) called.

18 after called.result:3

19 3

20 >>> 

 

 

 

增加补充表明:

 

  其实,装饰器就是叁个函数,一个得以用来包装函数的函数,最后回来八个修正之后的函数(这里的更换,例如扩展日志,如上例。)将其再度赋值原本的标志符,并永远丧失对原始函数对象的探访。

 

 

由于函数也是三个目的,况兼函数作为叁个破例的指标能够被赋值给别的变量(value = pringname(卡塔尔(قطر‎),相反,通过变量也是足以...

本文由js9905com金沙网站-金沙澳门手机版网址发布于计算机,转载请注明出处:js9905com金沙网站python的装饰器

您可能还会对下面的文章感兴趣: