一、装璜器
在初学装璜器的时候,会感觉形象生涩,其实装璜器就是对某个对象进行性能上的加强
上面具体讲一下“加强”的实现原理
二、加强的实现原理
其实原理就一句话:更改旧对象的指向,指向 结构的新的函数 wrapper
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
>>> now()
call now():
2015-3-25
下面是拿廖雪峰 -python- 装璜器中的例子,在此做一个具体阐明:
a. python 解释器在执行 now()
之前,首先加载环境,加载内存中对应的程序
b. 找到后,自上而下执行,于是先执行 @log
即执行:now = log(now)
咱们来具体看一下 log(now)产生了什么,重点关注指向对象的变动
1、首先解释器依据变量名 log,找到内存中对应的程序
2、now 函数传入 log 函数,重点来了,参数 func 和 now 此时指向同一个对象,即内存中存储的
```
def now():
print('2015-3-25')
```
3、此时解释器持续向下读取程序,直到遇到 return 返回。这里要留神,此时调用的是 log 函数,log 外部的 wrapper 函数 (闭包) 此时并没有被调用,所以此时执行 log 函数的 return 语句 `return wrapper`
log 函数将 `wrapper` 返回
c. log(now)返回wrapper
,而后赋值给 now,重点来了,now 变量指向的对象从
def now():
print('2015-3-25')
变为
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
d. abc 完结后,解释器执行完 @log,接下来读取到 now()语句,开始执行:
1. 此时 now 曾经和 wrapper 指向同一个对象,这里多说一句,其实此时如果运行
```
>>> now.__name__
'wrapper'
```
如果想要防止这种状况,能够应用 @functools.wraps(func)
2. 咱们继续执行,遇到 `print('call %s():' % func.__name__)`,执行 print 内容
3. 遇到 `return func(*args, **kw)`,还记得吗,下面咱们提到 func 指向的对象是谁?4. 调用 func
5. 解释器找到 func 指向的程序,```
def now():
print('2015-3-25')
```
6. 执行 `print('2015-3-25')`
e. 至此,now()执行完结,依据 abcd 的阐明,大家应该能够了解返回的后果了
>>> now()
call now():
2015-3-25
三、阐明
为了解释的通俗易懂,请大家疏忽下面一些话术用语的不精确。
这章内容没有波及到装璜器的“外函数只执行一次”这一知识点,这个知识点正好和
装璜器实现单例模式 相干,所以打算放到那里讲,有趣味的敌人能够去看。
四、考查
留一个小问题,now()的返回后果中,
为什么是 call now()
而不是 call wrapper()
?
hint:答案就在下面的解说中。