Python 装饰器

在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。

decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。

装饰没有参数的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def function(func):  # 定义了一个闭包

def func_in(): # 闭包内的函数

print('这里是需要装饰的内容,就是需要添加的内容')

func() # 调用实参函数。

return func_in


def test(): # 需要被装饰修改的函数。
print('无参函数的测试')


test = function(test) # 装饰器的原理就是将原有的函数名重新定义为以原函数为参数的闭包。

test() # 这里再次掉用test()的时候,其实是将会调用闭包内的函数func_in()。所以将会起到装饰修改的作用,最后会再次调用原函数test()。


# 装饰器的python写法,等价于test = function(test),并且无需调用当代码运行道这里,Python会自动运行。
@function
def test():
print('无参函数的测试')

test() # 这里再次调用函数时,将会产生修改后的效果。

装饰带有参数的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def function(func):  # 定义了一个闭包

def func_in(*args, **kwargs):
# 闭包内的函数,因为装饰器运行的实则是闭包内的函数,所以这里将需要有形参用来接收原函数的参数。

print('这里是需要装饰的内容,就是需要添加的内容')

func(*args, **kwargs) # 调用实参函数,并传入一致的实参。

return func_in


@function # 装饰器的python写法,等价于test = function(test) .
def test():
print('无参函数的测试')

# 这里再次掉用test()的时候,其实是将会调用闭包内的函数func_in()。
# 所以将会起到装饰修改的作用,最后会再次调用原函数test()。
test(5, 6)

装饰带有返回值的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def function(func):  # 定义了一个闭包

def func_in(*args, **kwargs):
# 闭包内的函数,因为装饰器运行的实则是闭包内的函数,所以这里将需要有形参用来接收原函数的参数。

print('这里是需要装饰的内容,就是需要添加的内容')

num = func(*args, **kwargs)
# 调用实参函数,并传入一致的实参,并且用变量来接收原函数的返回值,

return num # 将接受到的返回值再次返回到新的test()函数中。

return func_in


@function
def test(a, b): # 定义一个函数
return a + b # 返回实参的和

通用装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
def function(func):  # 定义了一个闭包

def func_in(*args, **kwargs):
# 闭包内的函数,因为装饰器运行的实则是闭包内的函数,所以这里将需要有形参用来接收原函数的参数。

print('这里是需要装饰的内容,就是需要添加的内容')

num = func(*args, **kwargs)
# 调用实参函数,并传入一致的实参,并且用变量来接收原函数的返回值,

return num # 将接受到的返回值再次返回到新的test()函数中。

return func_in

带有参数的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def func(*args, **kwags):
def function(func): # 定义了一个闭包

def func_in(*args, **kwargs):
# 闭包内的函数,因为装饰器运行的实则是闭包内的函数,
# 所以这里将需要有形参用来接收原函数的参数。

print('这里是需要装饰的内容,就是需要添加的内容')

num = func(*args, **kwargs)
# 调用实参函数,并传入一致的实参,并且用变量来接收原函数的返回值,

return num # 将接受到的返回值再次返回到新的test()函数中。

return func_in

return function


@func(50) # 这里会先运行函数func,并传入参数,之后会再次运行闭包函数进行装饰, @func(50)>>@function,然后将由@function继续进行装饰修改。
def test(a, b):
print('这是一个函数')

return a + b

类装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Test(object):  # 定义一个类

def init(self, func):
self.__func = func

def call(self): # 定义call方法,当直接调用类的时候,运行这里。

print('这里是装饰的功能')

self.__func()


t = Test() # 实例化对象

t() # 调用类,将会调用call方法。

"""
类装饰器等于test = Test(test),将函数test当作参数传入类中的init方法,
并将函数名赋值给私有属性__func,当函数test被调用的时候,其实是运行Test类中的call方法.
"""
@Test
def test():
print('被装饰的函数')


test() # 这里调用的不在是函数test,而是实例对象test的call方法,会先进行装饰,
# 然后再调用私有属性func(),func 其实就是被装饰的函数test