Python学习笔记|返回函数

Bruce
2023-12-24 / 0 评论 / 17 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年12月24日,已超过267天没有更新,若内容或图片失效,请留言反馈。

一、函数作为返回值

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

实现一个可变参数的求和:

# 可变参数求和
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,5,7,9)
#调用函数f,结果是<function __main__.lazy_sum.<locals>.sum()>
f
<function __main__.lazy_sum.<locals>.sum()>
# 调用函数f时,才真正求和结果
f()
25

调用lazy()函数时,每次调用都会返回一个新的函数,即使传入相同的参数。

f1 = lazy_sum(1, 3, 5, 7, 9)
f2 = lazy_sum(1, 3, 5, 7, 9)
f1 == f2
False
f1() == f2() #返回的值相同,评估为 True
True

二、闭包

(1)在函数嵌套(函数里面再定义函数)的前提下

(2)内部函数使用了外部函数的变量(还包括了外部函数的参数)

(3)外函数的返回值是内函数的引用

返回的函数并没有被立即执行,而是直到调用了f()才执行。

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

三个返回结果全部都是9,原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

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

如果要引用循环变量,需要再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。

def count():
    def f(j):
        def g():
            return j * j
        return g
    fs = []
    for i in range(1,4):
        fs.append(f(i)) # f(i)立即被执行,因此i的当前值被传入f()
    return fs
1
f1, f2, f3 = count()
f1()
4
f2()
4
f3()
9

如果对外层变量赋值,由于Python解释器会把x当作函数fn()的局部变量,它会报错:

def inc():
    x = 0
    def fn():
        # nonlocal x
        x = x + 1
        return x
    return fn

f = inc()
print(f()) # 1
print(f()) # 2

# 在x = x + 1的表达式中,Python解释器会认为x是一个局部变量,但是在此之前没有对x进行赋值操作,所以会报错。
# 要解决这个问题,可以在fn函数中加上nonlocal关键字,将x声明为非局部变量,这样就可以对x进行赋值操作。修改后的代码如下:
# def fn():
# nonlocal x
---------------------------------------------------------------------------

UnboundLocalError                         Traceback (most recent call last)

Cell In[44], line 10
      7     return fn
      9 f = inc()
---> 10 print(f()) # 1
     11 print(f()) # 2
Cell In[44], line 5, in inc.<locals>.fn()
      3 def fn():
      4     # nonlocal x
----> 5     x = x + 1
      6     return x
UnboundLocalError: local variable 'x' referenced before assignment

使用闭包,就是内层函数引用了外层函数的局部变量。如果只是读外层变量的值,我们会发现返回的闭包函数调用一切正常:

def inc():
    x = 0
    def fn():
        # 仅读取x的值:
        return x + 1
    return fn

f = inc()
print(f()) # 1
print(f()) # 1
1
1

小结变量。

一个函数可以返回一个计算结果,也可以返回一个函数。

返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。

练习:利用闭包返回一个计数器函数,每次调用它返回递增整数:

def createCounter():
    a = 0
    def counter():
        nonlocal a
        a += 1
        return a  
    return counter
f1 = createCounter()
print(f1())
print(f1())
print(f1())
1
2
3
0

评论 (0)

取消