Python学习之路(20)——装饰器

我们知道,对于Python语言而言,有一个很重要的概念——“一切皆对象”。

数字、字符串、元组、列表、字典等所有内置数据类型,以及函数、方法、类、模块等,在Python中所有的一切都是对象。它们都可以赋值给变量,或者可以作为参数传递给函数。

下面一个例子就是将Python中的函数作为参数传递给另一个函数,同事赋值给变量:

>>> def foo1():
	print("foo1()")

		
>>> def foo2(func):
	func()

	
>>> foo2(foo1)
foo1() 
>>> 
>>> foo3 = foo1
>>> foo3()
foo1()

   

实际上装饰器(Decorator)本质上是一个Python函数或类,它接收一个函数或类,并返回一个函数/类对象。在装饰器内部,可以让原函数或类在不需要做任何代码修改的前提下增加额外功能,进行“包装”。

 

比如一个hello代码:

>>> def hello(fn):
	def wrapper():
		print("hello, %s" % fn.__name__)
		fn()
		print("goodbye, %s" % fn.__name__)
	return wrapper

>>> @hello
def foo():
	print("i am foo")

	
>>> foo()
hello, foo
i am foo
goodbye, foo

  

可以看到:

1)函数foo定义前有一个@hello,hello就是在前面定义的函数hello

2)在hello函数中,需要一个fn的参数(这个就是用来做回调的函数)

3)hello函数中返回了一个inner函数wrapper,这个wrapper函数回调了传进来的fn,并在回调前后增加两条打印信息

 

Decorator的本质

对于Python的语法糖(Syntactic Sugar)@而言,当使用一个@decorator来修饰一个函数func时,

@decorator
def func():
    pass

其解释器会解释成如下:

func = decorator(func)

  

这不就是把一个函数当做参数,传递到另一个函数中,然后再回调吗?

是的,但是需要注意到,这里还有一个赋值语句,把decorator这个函数的返回值赋值回原来的func。

由于我们可以把函数当成变量来使用,所以,装饰器decorator必须得返回一个函数出来给func,这就是所谓的高阶函数(higher order function)。

 

回到hello()这个例子,我们可以看到,hello(foo)返回了wrapper()函数,所以foo其实编程了wrapper的一个变量,而后面的foo()其实编程了wrapper()。

至此,装饰器decorator的概念就基本清楚了吧?

posted on 2018-03-05 20:58  nicolas_Z  阅读(155)  评论(0)    收藏  举报

导航