Python装饰器进阶

Python fireling 8719℃ 0评论

Dobiasd的github上有一篇关于programming_language_learning_curves的文章,其中Python的学习曲线是这样子的。

python

 

可以看出,在Python学习中有一个概念非常关键,它是Python进阶的一个转折点,那就是装饰器(Decorators)。学好装饰器,你的Python功底及代码的威力将大大提高。

装饰器是什么?就是在不修改函数内部定义的前提下,在代码运行期间动态增加功能的方式。就是说,如果我们要增加某些功能,比如说打印日志,增加内存缓存,增加参数检测等等,可以在具体的函数内部定义,但是装饰器,则允许我们在不修改该函数的前提下实现这些功能,而且还能不费劲去增加你要优化的代码。下面列举几种常见应用:

1. 增加打印代码

def argument_print(f):
	def helper(x):
		print("input:", x)
		return f(x)
	return helper
@argument_print
def fib(n):
	if n == 0:
		return 0
	elif n == 1:
		return 1
	else:
		return fib(n-1)+fib(n-2)
print(fib(40))

2. 增加内存缓存

def memoize(f):
	memo = {}
	def helper(x):
		if x not in memo:
			memo[x] = f(x)
		return memo[x]
	return helper
@memoize
def fib(n):
	if n == 0:
		return 0
	elif n == 1:
		return 1
	else:
		return fib(n-1)+fib(n-2)
print(fib(40))

3.增加参数检测

def argument_test_natural_number(f):
	def helper(x):
		if type(x) == int and x >= 0:
			return f(x)
		else:
			raise Exception("Argument is not an integer")
	return helper
@argument_test_natural_number
def fib(n):
	if n == 0:
		return 0
	elif n == 1:
		return 1
	else:
		return fib(n-1)+fib(n-2)
print(fib(40))

当然,我们也可以使用多个装饰器来修饰同一个函数,同时达到多个我们需要的效果:

@argument_print
@memoize
@argument_test_natural_number
def fib(n):
	if n == 0:
		return 0
	elif n == 1:
		return 1
	else:
		return fib(n-1)+fib(n-2)
print(fib(40))

需要注意的是,在上述装饰器中,都定义了一个中间函数helper,由于它定义在函数内部并且利用到了当前外部环境变量f,因此它可以被看作是闭包。

装饰器的功能不仅仅在此,而且,如果我们想动态增加参数的话,可以使用带参数的装饰器。具体的做法主要是在之前的基础上,在外部加入一层函数定义,引入要使用的参数。这时原有的装饰器就在现有装饰器内形成了一个闭包。

转载请注明:宁哥的小站 » Python装饰器进阶

喜欢 (4)

您必须 登录 才能发表评论!