Python中的装饰器(decorator) - 函数装饰器

本文深入探讨Python中的装饰器,一种用于修改或增强函数和类的功能强大的设计模式。通过实例讲解如何使用装饰器进行函数增强、忽略函数执行、记录函数运行时间及重复执行函数。同时,介绍了如何使用类实现装饰器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python中的装饰器(decorator)并不是什么很神秘的火箭科技,但是妙用却很多。对于我等好学之徒,怎么能不深入研究呢?

先放相关代码地址:https://github.com/jiafangtao/web_programming/tree/master/py-decorators

 

关于decorator是什么,这里不做说明了,引用一段话,同学们细读就能理解了。

decorator in Python is any callable Python object that is used to modify a function or a class. A reference to a function "func" or a class "C" is passed to a decorator and the decorator returns a modified function or class.

关于“装饰器”设计模式,请自行参考GoF的《设计模式》一书。

 

下面跟随Bruce老师先看看代码,了解装饰器能够做什么。我们从最简单的函数装饰器入手。

#
# Some function decorators 
#

def increase(func):
	"""
	increase is a function decorator which adds 1 to the result of the callee
	"""
	def decorated_func(*args, **kwargs):
		result = func(*args, **kwargs)
		return result + 1

	return decorated_func

@increase
def get_dimensions():
	return 3

@increase
def plus(x, y):
	return x + y

##########################################################
def ignore(func):
	"""A decorator makes the callee being ignored"""
	def no_op(*args, **kwargs):
		return None
	return no_op

@ignore
def say_hello(greetings):
	print "hello, {}".format(greetings)


@ignore
def plus3(x, y, z):
	return x + y + z


#########################################################
# utility to log function durations
#########################################################
from datetime import datetime

def duration(func):
	def func_wrapper(*args, **kwargs):
		print "before calling function " + func.__name__
		startTime = datetime.now()
		ret = func(*args, **kwargs)
		endTime = datetime.now()
		d = endTime - startTime
		print "after calling function " + func.__name__
		print "duration is {} seconds".format(d.seconds + d.microseconds / 1000000.0)
	return func_wrapper


import time
import random

@duration
def a_time_consuming_func():
	timeout = 5 * random.random()
	time.sleep(timeout)


#
# decorations with parameters
#

def repeat(n):
	if (n <= 1):
		n = 1
	def repeat_decorator(func):
		def func_wrapper(*args, **kwargs):
			for i in range(n):
				func(*args, **kwargs)
		
		return func_wrapper

	return repeat_decorator

@repeat(3)
def draw_line():
	print "--------------------------------------"

if __name__ == '__main__':

	print get_dimensions()
	print plus(500, 500)

	say_hello('bruce.jia')

	print plus3(1, 2, 3)

	a_time_consuming_func()

	draw_line()

最容易实现的是无参数的装饰器,例如@increase和@ignore。使用过JUnit或NUnit的同学们看到@ignore的时候是不是觉得很熟悉呢!它会忽略掉它所装饰的函数。

@duration是个有用的小工具(utility),用来记录一个函数的运行时间。类似与@duration我们也可以用decorator来做安全检查,异常处理,支持实务等等。看到这里,熟悉JAVA的同学是不是想起熟悉的AOP,没错,decorator跟AOP有异曲同工之处。

 

接下来的@repeat复杂一点,它是一个带参数的decorator。例如重复执行函数三次,可以写@repeat(3)。注意它的实现方式,它其实是一个普通函数,返回一个decorator。而之前的无参数的decorator,返回一个普通函数。

 


下面的代码跟上边的不同之处,是使用类来实现decorator。

class Auth:

	def __init__(self, func):
		self._func = func

	def __call__(self):
		print "authenticate the user before calling the function {}".format(self._func.__name__)
		print "......"
		return self._func()


@Auth
def get_my_balance():
	return 99999999999

if __name__ == '__main__':
	print "I'm rich that I have {} dollars".format(get_my_balance())

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bruce Jia(上海)

熬夜码字换酒钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值