0x00000000030A40D0位置(这个位置应该是指内存位置)存有一个function(方法)叫target;在 target后面加上(),表示调用该方法,即输入target(),“大脑”便按照target方法所写的代 码逐条执行,于是打印出了target字符串,并且“大脑”明白在0x00000000030A4268位置有一 个叫returnme的方法;因为target对象调用后是会返回一个returnme方法,并且方法是可以被调用的,因 此你可以直接这样书写target()(),“大脑”会逐条执行target中的代码,然后return一个 returnme,因为多加了一个(),表示要对返回的returnme进行调用,于是再次逐条执行returnme中的代码 ,最后便能看到15、16的打印结果;而returnme方法是没有返回任何可调用的对象,因此当输入 returnme()()时,“大脑”会报错。
下面我们可以来解释一下脚本2和脚本3的运行详情,之前说过,装饰器的工作原理就是脚本1代码所演 示的那样。
@decorator
def target():
...
等同于
def decorator(target)():
...
注:python语法中以上写法是非法的,以上只是为了便于理解。
当你调用被装饰方法target时,其实首先被执行的是作为装饰器的decorator函数,然后“大脑 ”会把target方法作为参数传进去,于是:
#脚本2
def decorator(func):
func()
print('this is decorator')
@decorator
def target():
print('this is target')
target
-------------------------------------------
实际运行情况:
首先调用decorator方法:decorator()
因为decorator方法含1个参数,因此将target传入:decorator(target)
运行代码“func()”,根据传入的参数,实际执行target(),结果打印出:this is target
运行代码"print('this is decorator')",结果打印出:this is decorator
对比脚本3的运行情况:
#脚本3
def decorator(func):
func()
print('this is decorator')
@decorator
def target():
print('this is target')
target()
-------------------------------------------
实际运行情况:
首先调用decorator方法:decorator()
因为decorator方法含1个参数,因此将target传入:decorator(target)
运行代码“func()”,根据传入的参数,实际执行target(),结果打印出:this is target
运行代码"print('this is decorator')",结果打印出:this is decorator
以上与脚本2中运行情况完全相同,接下来便是执行脚本2中target没有的(),也就是执行调用命令。
由于decorator(target)没有返回一个可以被调用的对象,因此“大脑”提示错
误:'NoneType' object is not callable
如果你还不是很清楚,请看下面的等价关系:
@decorator
def target():
...
等同于
def decorator(target)():
...
因此:
target == decorator(target)
target() == decorator(target)()
所以:
假设有一个变量var=target,在将target赋值给var时,其实是将decorator(target)的调用结果赋值给
var,因为var不具备调用性(not callable),因此执行var()时,编译器会报错它是个NoneType对象,
不能调用。
综上所述,你大概已经能够明白所谓的装饰器是怎么一回事,它是怎么工作的。但脚本2和脚本3中的 写法会带来一些困惑,这个困惑就是通过我们编写的decorator装饰器对target进行装饰后,将target变 成了一个永远不能被调用的方法,或者说变成了一个调用就报错的方法。这跟我们的使用习惯以及对方法 的认识是很不协调的,毕竟我们还是习惯一个方法天生注定可以被调用这种看法。所以为了满足我们对方 法的定义,我们最好将作为装饰器的方法写成一个可以返回具有被调用能力的对象的方法。
#脚本4
def whatever():
print('this is whatever')
def decorator(func):
func()
print('this is decorator')
return whatever #1
@decorator
def target():
print('this is target')
------------------------------
输入:target
结果:
this is target
this is decorator
输入:target()
结果:
this is target
this is decorator
this is whatever
在#1的位置,你可以return任何可以被调用的方法或类,甚至你可以直接写成:
def whatever():
print('this is whatever')
def decorator(func):
return whatever