专栏首页机器学习实践二三事python基础----函数作为返回值

python基础----函数作为返回值

从一个例子讲起

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。 还是考虑这个问题:对可变参数进行求和 看了上一讲的已经知道,可以使用’*’来表示接受一个tuple参数,代码大概可以这样写:

def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n
    return ax

但是这有个问题,如果我不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办? 解决方法是:将函数作为返回值返回,不返回结果只返回函数

解决方法代码:

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum
>> f = lazy_sum(1, 3, 2, 7, 9)
>> f
<function sum at 0x10452f668>

可以看到,我们返回的只是sum这个函数并没有返回函数计算得到的值 可以这样调用:

>> f()
>> 22

此时才是真正的计算出函数值;

闭包

我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”

>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
False

f1()和f2()的调用结果互不影响;

注意: 返回的函数并没有立刻执行,而是直到调用了f()才执行,所以如果你的参数绑定的是循环变量,意味着你的变量值会随着迭代来改变,此时会出现你不想要的结果; 比如下面的例子:

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

理论上应该返回1,4 ,9,但是结果是:

>>> f1()
9
>>> f2()
9
>>> f3()
9

全是9,原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9; 返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

>>> def count():
...     fs = []
...     for i in range(1, 4):
...         def f(j):
...             def g():
...                 return j*j
...             return g
...         fs.append(f(i))
...     return fs
... 
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

同时可以使用lambda函数缩短代码;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Hadoop之--集群环境搭建

    上篇博客介绍了HDFS的相关框架与理念,这篇博客介绍如何搭建Hadoop集群 前期准备 我因为没有实体的多台主机,只有自己一台主机,所以决定借助VirtualB...

    GavinZhou
  • 数字图像学习1

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.n...

    GavinZhou
  • 深度学习论文资源(截至2016年)

    从全局到枝干、从经典到前沿、从理论到应用、还有最新的研究…,所有你不需要的需要的,现在不需要的未来需要的,你不需要的周边小伙伴需要的…反正全都在这了。拿走不谢,...

    GavinZhou
  • Spark 2.2 on K8S 和 Kubernetes v1.14

    就像之前写过很多关于 Spark on K8S 的文章,Spark 2.2 是 Fork 出来的版本,虽然经受住了我们部门超大规模的 Spark 计算业务的考验...

    runzhliu
  • 虚拟主机和云服务器怎么选?

    虚拟主机已经有了一段时间的历史,近几年随着其技术的不断成熟,以及其低廉的价格,成为众多站长的首选对象。但近两年云计算的出现,衍生出云服务器这个产物。这时,很多站...

    用户6429551
  • 虚拟主机和云服务器怎么选?

    虚拟主机已经有了一段时间的历史,近几年随着其技术的不断成熟,以及其低廉的价格,成为众多站长的首选对象。但近两年云计算的出现,衍生出云服务器这个产物。这时,很多站...

    尊托云数
  • DVM三问—说说虚拟机

    上一节说了Android的五层架构,今天说说其中的Dalvik虚拟机,简称DVM。

    码上积木
  • aiohttp文档翻译-server(一)

    一个 request handler 必须是一个coroutine (协程), 它接受一个Request实例作为其唯一参数,并返回一个Response 实例,如...

    coders
  • vue全家桶之vuex

    状态管理可以简单理解为vue中的某些全局的data属性。 当组件状态增多时,整个应用和状态分散在每个组件和实例中。部分还会出现状态共享。这时最好的方案就是vue...

    一粒小麦
  • 前端实时更新后端处理进度之 进度条实现

    用全局变量记录处理进度, return_result函数负责具体任务,同时更新后台进度值,return_width负责将当前进度值返回给前端。当全局变量不被识别...

    PedroQin

扫码关注云+社区

领取腾讯云代金券