python最常用七大函数(三)之返回函数和匿名函数

153 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

一、返回函数

Python 的函数不但可以返回int 、str 、list 、dict 等数据类型,还可以返回函数!

例如,定义一个函数 f() ,我们让它返回一个函数 g ,可以这样写:

def f():

    print 'call f()...'

    # 定义函数g:

    def g():

        print 'call g()...'

    # 返回函数g:

    return g

仔细观察上面的函数定义,我们在函数 f 内部又定义了一个函数 g 。由于函数 g 也是一个对象,函数名 g 就是指向函数 g 的变量,所以,最外层函数 f 可以返回变量 g ,也就是函数 g 本身。

调用函数 f ,我们会得到 f 返回的一个函数:

>>> x = f()   # 调用f()

call f()...

>>> x   # 变量x 是f() 返回的函数:

<function g at 0x1037bf320>

>>> x()   # x 指向函数,因此可以调用

call g()...   # 调用x() 就是执行g() 函数定义的代码

请注意区分返回函数和返回值:

def myabs():

    return abs   # 返回函数

def myabs2(x):

    return abs(x)   # 返回函数调用的结果,返回值是一个数值

返回函数可以把一些计算延迟执行。例如,如果定义一个普通的求和函数:

def calc_sum(lst):

    return sum(lst)

调用calc_sum() 函数时,将立刻计算并得到结果:

>>> calc_sum([1, 2, 3, 4])

但是,如果返回一个函数,就可以“延迟计算”:

def calc_sum(lst):

    def lazy_sum():

        return sum(lst)

    return lazy_sum

# 调用calc_sum() 并没有计算出结果,而是返回函数:

>>> f = calc_sum([1, 2, 3, 4])

>>> f

<function lazy_sum at 0x1037bfaa0>

# 对返回的函数进行调用时,才计算出结果:

>>> f()

10

由于可以返回函数,我们在后续代码里就可以决定到底要不要调用该函数。

请编写一个函数calc_prod(lst) ,它接收一个list ,返回一个函数,返回函数可以计算参数的乘积。

def calc_prod(lst):

    def lazy_prod():

        def f(x, y):

            return x * y

        return reduce(f, lst, 1)

    return lazy_prod

f = calc_prod([1, 2, 3, 4])

print f()

二、匿名函数

高阶函数可以接收函数做参数,有些时候,我们不需要显式地定义函数,直接传入匿名函数更方便。

在Python 中,对匿名函数提供了有限支持。还是以map() 函数为例,计算 f(x)=x2 时,除了定义一个f(x) 的函数外,还可以直接传入匿名函数:

 map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])

[1, 4, 9, 16, 25, 36, 49, 64, 81]

通过对比可以看出,匿名函数 lambda x: x * x 实际上就是:

def f(x):

    return x * x

关键字lambda 表示匿名函数,冒号前面的 x 表示函数参数。

匿名函数有个限制,就是只能有一个表达式,不写return ,返回值就是该表达式的结果。

使用匿名函数,可以不必定义函数名,直接创建一个函数对象,很多时候可以简化代码:

sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y))

[9, 5, 3, 1, 0]

返回函数的时候,也可以返回匿名函数:

myabs = lambda x: -x if x < 0 else x

myabs(-1)

利用匿名函数简化以下代码:

def is_not_empty(s):

    return s and len(s.strip()) > 0

filter(is_not_empty, ['test', None, '', 'str', '  ', 'END'])

定义匿名函数时,没有return 关键字,且表达式的值就是函数返回值。

参考代码:

print filter(lambda s: s and len(s.strip())>0, ['test', None, '', 'str', '  ', 'END'])