装饰器导致的误会——为什么我的参数变多了?

装饰器其实一点都不难,两个例子基本够了:

第一个例子:

def dec(func):
    def com(a,b):
        i=func(a,b)
        return i+a+b
    return com

@dec
def add(x,y):
    return x+y

add(1,2)

读这种代码的要点在于掌握“ 装饰器是把函数作为参数传入,并重新赋值给原函数 ”这个要点,即:


#上一条代码中
@dec
#这条语句相当于是:
add=dec(add)

重写一下代码,两者其实是等价的:

def dec(func):
    def com(a,b):
        i=func(a,b)
        return i+a+b
    return com

def add(x,y):
    return x+y

add=dec(add)

add(1,2)

那么,在遇到这种简单的装饰器的时候,阅读的时候掌握小窍门,看见add(1,2), 要分开看,仿佛看见是看见了add和(1,2),而不是add(1,2)这个整体。

那么上面的代码看起来就很简单了:

看见add(1,2),相当于看见了dec(add)(1,2)

因为dec(add)的返回值为com,所以dec(add)(1,2)相当于com(1,2)

然后直接根据com()的定义去算即可,注意一下func其实就是输入的add就可以了。

第二个例子:

和第一个例子差不多,只是多了一个参数在装饰器里传递:

def bcd(c):
    def dick(func):
        def y(a,b):
            i=func(a,b)+c
            return i
        return y
    return dick

@bcd(2)
def abc(a,b):
    return a+b

abc(1,2)

这种情况下,相当于是:

def bcd(c):
    def dick(func):
        def y(a,b):
            i=func(a,b)+c
            return i
        return y
    return dick

def abc(a,b):
    return a+b

abc=bcd(2)(abc)

abc(1,2)

也就是说,看见abc(1,2),相当于看见bcd(2)(abc)(1,2)

因为bcd(2)返回值为dick,所以相当于dick(abc)(1,2)

因为dick(abc)返回值为y,所以相当于y(1,2)

然后就把1,2代入y(a,b)计算,注意一下func是传入的add,c是传入的2即可

最后,我们来看参数变多的情况:

def dec(func):
    def com(a,b,c=2):
        i=func(a,b)+c
        return i+a+b
    return com

@dec
def add(x,y):
    return x+y

add(1,2,4)

上面的语句,如果不掌握装饰器,就会很让人懵逼:明明add(x,y)只有两个参数,为什么add(1,2,4)有三个参数还不报错?

其实很简单,无非是装饰器对add函数做了改写:

add(1,2,4)在装饰器的作用下,相当于dec(add)(1,2,4)

因为dec(add)返回为com,所以相当于com(1,2,4). 这里可以发现com其实是带了三个参数位置的,所以add(1,2,4)的写法没有错。

但是下面这种写法不行,原因也很简单,因为func在这里其实就是add(x,y),只有两个参数位,不能写第三个:

def dec(func):
    def com(a,b,c=2):
        i=func(a,b,1)+c
        return i+a+b
    return com

@dec
def add(x,y):
    return x+y

add(1,2,4)


#运行结果如下:
-------------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [5], in <cell line: 11>()
      7 @dec
      8 def add(x,y):
      9     return x+y
---> 11 add(1,2,4)

Input In [5], in dec.<locals>.com(a, b, c)
      2 def com(a,b,c=2):
----> 3     i=func(a,b,1)+c
      4     return i+a+b

TypeError: add() takes 2 positional arguments but 3 were given

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值