2、Python 函数作为返回值

部署运行你感兴趣的模型镜像

函数作为返回值
高阶函数除了可以接收函数作为参数外,还可以把函数作为结果值返回。

我们来实现一个可变参数的求和。通常情况下,求和的函数是这样定义的:

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

f = lazy_sum(1,2,3,4,5)
print f
# <function sum at 0x02657770>
# lazy_sum(1,2,3,4,5)返回的是一个指向求和的函数的函数名。
# 在调用lazy_sum(1,2,3,4,5)的时候,不立刻求和,而是根据后面代码的需要在计算。
print f()
# 15
# 用f()调用求和函数,计算出结果。

f1 = lazy_sum(1,2,3,4,5,6)
f2 = lazy_sum(1,2,3,4,5,6)
print f1 == f2
# False
# lazy_sum()每调用一次,都会返回一个独一无二的函数地址。    

例中,lazy_sum中的内部函数sum引用了外部函数lazy_sum的参数和局部变量,
当lazy_sum返回函数sum时,相关参数和变量已经保存在返回的函数sum中了。
我们称这为 闭包

 

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。

另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:

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

f1, f2, f3 = count()
print f1()
print f2()
print f3()
# 9
# 9
# 9

 

结果全部都是9. 不是预期的1,4,9!

遂在编辑器中不断更改并调试运行观察变量的变化过程:

# -*- coding: utf-8 -*-

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

# f1, f2, f3 = count()
#将上述代码分开写:
f1 = count()
f2 = count()
f3 = count()

print(f1())
print(f2())
print(f3())

 

结果编译器报错:

Traceback (most recent call last):
File "***.py", line 16, in <module>
print(f1())
TypeError: 'list' object is not callable

调试后发现原因:

f1 = count()这条语句执行时,count()函数会先执行,并将结果fs(这是一个包含三个元素(值是三个不同函数)的list!)返还f1。所以f1()是将list当函数用,故报错!

f2 = count()和f3 = count()也是这个道理。

所以第一个要弄清楚的是 :初始代码中的f1, f2, f3 = count()是将count() 中返回值(list)的三个元素(元素值是函数)分别赋值给f1,f2,f3!此时它们是函数!

修改代码:

# -*- coding: utf-8 -*-

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

# f1, f2, f3 = count()
f1 = count()
f2 = count()
f3 = count()

print(f1[0]())
print(f2[0]())
print(f3[0]())

 

结果仍然是:

9

9

9

 

调试后发现,运行f1[0]() 后:

 因为f1[0]()中存放的就是函数f, 但此时i是3,故返回输出9!

 所以返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

posted on 2018-02-07 21:38 Hello _ world 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/zwb8848happy/p/8428517.html

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

### Python 函数返回值的原因 当 Python 函数执行完毕而未遇到 `return` 语句时,默认会返回特殊对象 `None`。这表示该函数实际上是有返回值的,只是这个返回值是 `None` 而已[^1]。 ```python def func_without_return(): pass result = func_without_return() print(result is None) # 输出 True ``` 如果希望函数能够提供有意义的结果,则应在适当位置加入 `return` 语句来指定要返回的数据。 ### 如何使 Tkinter 按钮回调函数返回值 对于Tkinter按钮点击事件处理程序而言,由于这些方法通常是在GUI主线程内异步触发的,因此无法直接获取它们的实际返回值[^4]。不过可以通过其他方式间接取得所需数据: - **全局变量法** 利用外部作用域中的可变容器(如列表或字典),由回调函数更新其中的内容; ```python from tkinter import * root = Tk() data_container = [] def on_button_click(): global data_container value_to_store = "some computed result" data_container.append(value_to_store) Button(root, text="Click Me", command=on_button_click).pack() mainloop() print(data_container[-1]) # 访问最后存储的结果 ``` - **类属性保存结果** 创建自定义控件类,在实例成员里维护状态信息; ```python class MyButton(Button): def __init__(self, master=None, cnf={}, **kw): super().__init__(master, cnf, kw) self.result_storage = [] def handle_click(self): new_result = "another calculated outcome" self.result_storage.append(new_result) my_btn = MyButton(text='Press Here', command=my_btn.handle_click) my_btn.pack() mainloop() print(my_btn.result_storage[-1]) ``` 这两种策略都可以有效地绕过直接捕获回调函数返回值的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值