python装饰器副作用_对Python 装饰器的理解心得

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值