https://blog.csdn.net/try_test_python/article/details/80802199
前几天在学装饰器的时候,关于装饰器内层函数调用目标函数时是否return目标函数的调用产生了一点迷惑,事实是当被装饰的目标函数有返回值的时候,装饰器内层函数也必须返回该目标函数的调用。
我们都知道不带括号的函数名指向是函数代码所在的内存地址,加上括号之后就变成了一个执行命令,那么这个‘func( )’到底有什么意义呢?
上面这张图可以大概看出点东西,单独的函数名是 function类的一个实例对象,而函数名() 则没有任何类型,是个无类型。
然后看这张图,一个无返回值的函数调用指向的内存地址和 ‘None’的内存地址是同一个,说明什么呢,说明函数名()很可能也是个变量。那这个变量里面装的什么东西呢,从上面两张图可以看得出,它里面什么也没有。
同样的,print()作为解释器自带的函数同样也指向了空。
这三张图想说明什么呢,可能有点乱,但是结论也很清楚,func()仅仅是告诉系统要执行其函数名指向的那段代码,剩下的没有别的意义,任何函数名加上括号,那就是执行的信号,告诉系统,我要执行。(其实任何可调用类型都是这样)
然后开始进入关于return的一些研讨。
在装饰器里,闭包的内层函数对目标函数的处理是否return,结果很不一样。
先看上面这块代码,当函数往外有返回值的时候,func()的指向就不一样了,它此时指向的是返回值所在的内存地址,我们上面已经得到了一些结论,那就是函数没有返回值的时候,func()是空的,有了返回值,那么它就成了指向返回值的这么个变量。所以,func()除了作为执行代码的信号之外,还用来保管函数的返回值。
我们可以理解为,func()是一个容纳函数运行附加值的容器,return的作用就是将这个附加值往外传递,传递给谁呢,传递给func()这个变量。下面做个小实验:
如上图所示,return将函数的返回值赋值给所在的“函数名()”,而函数名()这个变量也因为所装载的数据而改变了类型:
如图,func1()的类型变成了整型。
也就是说,如果一个函数有了结果而不往外传递这个结果的话,那么这个结果就算是被丢弃了,作为这个函数的‘首席’接受者,函数名()将仅仅是函数运行的一道代表命令的字符,除此之外,什么也不是。
现在讨论装饰器中return的必要性。
上面三张图分别是未经过装饰器扩展时目标函数的执行结果,然后是加了装饰器,但是没有返回函数结果和返回了函数结果的三种情况。
我们知道,装饰器的作用就是给目标函数扩展功能,基本原则是不能影响原函数的功能,所以不加return的话,原函数的基本功能都受到影响了,必须对原函数的返回值进行再次return。
现在我们来说结论,函数名是指代的函数代码所在的空间,函数名加括号,指代的是函数往外传递的数据,而return就是往外传递数据的工具,如果函数名()没有接收到return出来的数据,那么“函数名()”除了执行命令外,什么也不是,函数往外传递的数据就丢失了。
装饰器的核心在于闭包的内层函数,外层函数将目标函数拿来加工,用内层函数包裹目标函数的代码,然后将这一整块代码返回给目标函数的函数名,现在目标函数的函数名(代号func)指向的是加工过的函数代码,原来的代码成了外来户,所以原来代码传递的数据如果没有中间人进行传递的话,func将不能接收那个数据,那个数据就丢失了。func()原来可以容放原函数返回值,现在就什么都没有了。所以,return是很有必要的。
---------------------
作者:haiton大人
来源:CSDN
原文:https://blog.csdn.net/try_test_python/article/details/80802199?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!