为了账号安全,请及时绑定邮箱和手机立即绑定

谁能解释一下装饰器精髓?下面这两种写法,右边写法比起左边少了fn(x)函数,不是更加简洁了吗?

谁能解释一下装饰器精髓?下面两种写法的结果完全一样,为什么第一种叫装饰器。并且右边比起左边少了fn(x)函数,不是更加简洁了吗??

def f1(x):                                    def f2(x):  

    return x*2                                     return x*2


def new_fn(f):                            def new1_fn(f,x):

    def fn(x):                                        print('call')

        print('call')                                  return f(x)

        return f(x)                          f2=new1_fn(f2,5)

    return fn                                print(f2)


f1 = new_fn(f1)

print(f1(5))


正在回答

9 回答

个人理解,返回函数是为了延迟调用,在这个题目下,延迟调用可以理解为延迟输入参数,右边在

f2=new1_fn(f2,5)时已经是得到了一个数,而左边的f1 = new_fn(f1)还是一个函数。相当于说右边在重新定义f2的时候将f2直接变成了一个数了
0 回复 有任何疑惑可以回复我~

“装饰器”顾名思义是起到装饰的作用,我理解成在不对原函数做出任何修改的情况下对函数增加前缀或者后缀,而你右边显然是对原函数进行修改来着,你想想如果你右边换一个函数,比如变成带两个参数的函数是不是又得重新写一个?

2 回复 有任何疑惑可以回复我~

右边的代码的问题在于,你在新建一个函数的时候一定要自变量赋值,而左边的不需要。  左边的效果是,给原来的函数增加了一个写日志的功能,其它什么都不用变。

左边 :  f1 = new_fn(f1)#此时f1是一个真正的函数。 只是添加了一个写日志的功能而已。   

右边:f2=new1_fn(f2,5) #此时f2是一个函数值,而不是函数。  

1 回复 有任何疑惑可以回复我~

装饰器的返回值是闭包函数,右边返回的不是函数。不能延迟调用。从本质上来讲装饰器调用完毕,返回的是一个闭包函数(持有自己的状态),该闭包在装饰器函数调用结束后,并不会销毁所持有的被装饰的原始函数变量。(注意,正常函数调用完毕,会释放掉函数内部变量),只是产生了一个新的函数,新函数外观与被装饰函数一样,但在不改变原函数的情况情况下却加料了。

2 回复 有任何疑惑可以回复我~

你这两种代码,咋一看没区别,其实有区别的啊,本质上的区别就是:

左边的是最后调用的时候,是调用fn(x),fn(x)函数封装了变化,实际上print('call')与原来的f1函数是作为一个整体封装咋fn(x)里面,print是在f1函数上的拓展。

而右边,不能看成是拓展,你只能看成是在原f2函数的逻辑之前,在加了一个print('call')打印的逻辑。

如果还是有点懵逼,我只能举个粒子了:

你试试左边再多调用几次

print(f1(6))

print(f1(7))

这当然是正常的,但是右边很容易出问题,如果你是这样写

f6=new1_fn(f2,6)

print(f6)

f7=new1_fn(f2,7)

print(f7)

恭喜你,还是正常的,但是我们知道为什么返回函数?就是为了延迟调用,我们把顺序调转一下,做延时调用

f6=new1_fn(f2,6)

f7=new1_fn(f2,7)

print(f6)

print(f7)

如果你看出来了,那么恭喜你,你明白这两种方式的区别,并且也清楚,右边的写法,不能算是函数的拓展。

3 回复 有任何疑惑可以回复我~

装饰器的作用是,避免后面重复写代码,提高效率,所以直接@函数名即可,但是右边虽然现在是简洁,但如果后续要大量使用此代码的时候,用不了@的写法,因为右边的不是装饰器正确写法,到时候按照右边的写的话,需要用一次写一次,很麻烦。

2 回复 有任何疑惑可以回复我~

装饰器精髓在于可以不改变函数的参数返回值等的情况下动态添加函数功能(比如说打印log)

左边是装饰器写法,新旧f1都是接受一个参数返回相同计算结果

右边的新f2已经没有参数了,参数在定义新f2的时候已经传入,与原函数格式不同

0 回复 有任何疑惑可以回复我~
#1

慕粉1024298749

使用装饰器时,你调用新旧函数的方式是一样的
2018-11-15 回复 有任何疑惑可以回复我~

f1=new_fn(f1),这个当中,f1是函数名也是变量名

0 回复 有任何疑惑可以回复我~
#1

慕粉1500434311 提问者

右边那种写法也是呀,而且比起左边少了fn(x)函数,不是更加简洁了吗
2018-11-04 回复 有任何疑惑可以回复我~

装饰器是种高阶函数,在运行的时候可以动态的增加被装饰的函数功能。

0 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
python进阶
  • 参与学习       255665    人
  • 解答问题       2949    个

学习函数式、模块和面向对象编程,掌握Python高级程序设计

进入课程

谁能解释一下装饰器精髓?下面这两种写法,右边写法比起左边少了fn(x)函数,不是更加简洁了吗?

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信