系统学习Python——装饰器:函数装饰器-[对方法进行装饰:使用嵌套函数装饰方法]

分类目录:《系统学习Python》总目录


如果想要函数装饰器在简单函数和类级别的方法上都能工作,最直接的解决办法在于使用前面文章介绍的状态保持方案之一:把自己的函数装饰器编写为嵌套的def,这样你就不会陷入单一的self实例参数既是包装器类实例,又是主体类实例了的困境。

如下的替代方案用Python3.X的非局部变量进行了修补;如果要在Python2.X下使用,则可以重新编写它,为可更改的calls状态变量使用函数属性。由于被装饰的方法重新绑定到了简单函数而不是实例对象,所以Python正确地传递了Person对象作为第一位参数,并且装饰器将其从*args中的第一项传递给真正被装饰方法的self参数:

def tracer(func):
	calls = 0
	def onCall(*args, **kwargs):
		nonlocal calls
		calls += 1
		print('call %s to %s' % (calls, func.__name__))
		return func(*args, **kwargs)
	return onCall

if __name__ == '__main__':
	@tracer
	def spam(a, b, c):
		print(a + b + c)

	@tracer
	def eggs(N):
		print(2 ** N)

	span(1, 2, 3)
	span(a=4, b=5, c=6)
	print(eggs(32))

	class Person:
		def __init__(self, name, pay):
			self.name = name
			self.pay = pay

		@tracer
		def giveRaise(self, percent):
			self.pay *= (1.0 + percent)

		@tracer
		def lastName(self):
			return self.name.split()[-1]

	print('methods...')
	bob = Person('Bob Smith', 50000)
	sue = Person('Sue Jones', 100000)
	print(bob.name, sue.name)
	sue.giveRaise(0.1)
	print(sue.pay)
	print(bob.lastName(), sue.lastName())

我们还在一个__name__测试下缩进了文件的自测试代码,这样装饰器就能够在其他地方导人和使用。这个版本在函数和方法上都有效,但由于其使用了nonlocal,它只能在Python3.X中运行:
输出结果我们可以跟踪运行这些结果,以确保我们能够驾驭这一模型;后面的文章还将提供了它的一个支持类的替代方案,但是更为复杂。

参考文献:
[1] Mark Lutz. Python学习手册[M]. 机械工业出版社, 2018.

猜你喜欢

转载自blog.csdn.net/hy592070616/article/details/135330534