Python装饰器

装饰器是什么意思

一个大牛举的例子:

内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。

装饰器本质上是Python函数,可以为已存在的对象添加额外的功能,同时装饰器还可以抽离出与函数无关的重用代码。具体应用场景如:插入日志、性能测试、事务处理、缓存、权限校验等。

举个栗子

需要在某个原有功能上加一层验证

def a():

print 'a'

def b():

print 'a'

  • 1
  • 2
  • 3
  • 4
  • 5

a b 方法很多地方调用,不想更改原有调用方式

即:

def a():

权限验证

print 'a'

def b():

权限验证

print 'a'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

假如有很多的接口—-

用装饰器来实现:

def auth(func):

def inner():

# 验证1

return func()

return inner

@auth

def a():

print 'a'

@auth

def a():

print 'b'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

带参数装饰器

执行方法带参数

def auth(func):

def inner(arg1,arg2):

# 验证1

return func(arg1,arg2)

return inner

@auth

def a(arg1,arg2):

print 'a'

@auth

def b(arg1,arg2):

print 'b'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

装饰器带参数

def auth(info):

def decorator(func):

def inner(arg1,arg2):

# 验证1

print info

return func(arg1,arg2)

return inner

return decorator

@auth(info='a')

def a(arg1,arg2):

print 'a'

@auth(info='b')

def b(arg1,arg2):

print 'b'

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

类装饰器

再来看看类装饰器,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器还可以依靠类内部的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

class Foo(object):

def __init__(self, func):

self._func = func

def __call__(self):

print ('class decorator runing')

self._func()

print ('class decorator ending')

@Foo

def bar():

print ('bar') bar()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

装饰器执行顺序

@a

@b

@c

def f ():

等于

f = a(b(c(f)))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

带来的问题(知乎刘志军大牛)

使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了,比如函数的docstring、name、参数列表

这个问题就比较严重的,好在我们有functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中,这使得装饰器函数也有和原函数一样的元信息了。

from functools import wraps

def logged(func):

@wraps(func)

def with_logging(*args, **kwargs):

print func.__name__ + " was called"

return func(*args, **kwargs)

return with_logging

@logged

def f(x):

"""does some math"""

return x + x * x

print f.__name__ # prints 'f'

print f.__doc__ # prints 'does some math'

Python装饰器

相关推荐