52、Python之函数高级:作为一等公民的函数对象

引言

从这篇文章开始,打算花一定的篇幅对Python中的函数作为一等公民的特性,进行稍微深入一点的探究。

在Python之函数高级这个模块中,大概会涉及到高阶函数、闭包、装饰器,以及函数式编程等内容。

希望通过这些内容的介绍,Python初学者或者从其他编程语言转过来的编程老手,能够对Python中关于一切皆对象的设计理念,以及函数天然作为一等公民的特性有更加深入的理解,更加自然地应用高阶函数及函数式编程。

本文作为该模块的开篇,打算在介绍Python函数高级的内容之前,系统地回顾一下Python中函数作为一等公民所带来的便捷性。

本文的主要内容有:

1、“一等公民”的条件

2、函数作为一等公民的权利

3、其他编程语言中函数的使用

“一等公民”的条件

编程语言中“一等公民”的概念,是指某种类型,比如:函数、对象等,在实际编程中,可以像普通类型一样被自由地操作和使用,而没有任何限制。

更加直观地理解,所谓“一等公民”,自然是权力范围很大,普通类型能去的地方,它都能去,才算得上是“一等公民”。

在编程语言中,某个类型是否被认为是“一等公民”,主要看代码中的这些地方,它是否可以去:

1、可以像普通类型一样,出现在赋值语句中,将该类型的实例赋值给变量。

2、可以像普通类型一样,可以存储在数据结构中,比如数组、字典等。

3、可以像普通类型一样,作为函数的参数进行传递。

4、可以像普通类型一样,作为函数的返回值。

函数作为一等公民的权利

既然,我们说Python中一切皆对象,函数对象是一等公民,那么一等公民该有的权利,能去的地方,函数自然也能去得。其实,这些内容在前面的文章中也有介绍过,这里再回顾一下。

接下来,我们通过代码来分别验证一下:

1、将函数赋值给变量

如果已经比较深刻地理解了Python中的数据模型,即一切皆对象;以及Python中的“名称绑定”的概念,即变量名是贴在对象上的标签。那么,一定能够轻易理解将函数赋值给变量的用法。

直接看代码:

def add(a, b):
    return a + b


plus = add
print(plus(10, 20))
print(add)
print(plus)

执行结果:

10c62fd057f6332d2a6066d052dbd31e.jpeg

代码比较简单,这里就不作过多解释了,从“名称绑定”来看,add和plus都是同一个函数对象上绑定的不同名称,类似于贴上了两个不同标签。

2、将函数存储在数据结构中

还是以四则运算为例,我们定义加减乘除四个函数,然后计算两个数字的四则运算结果。这里,我们考虑用列表存储运算函数,通过列表推导式计算运算结果。

代码如下:

def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def multiply(a, b):
    return a * b


def divide(a, b):
    return a / b


computations = [add, subtract, multiply, divide]
print(computations)
results = [compute(20, 10) for compute in computations]
print(results)

运算结果:

df2ad844ba72745a8abd70f45e250637.jpeg

3、将函数作为参数传递

同样是四则运算的例子,这次我们定义一个compute()函数,接收第一个参数为进行的运算方式的函数。直接看代码:

def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def multiply(a, b):
    return a * b


def divide(a, b):
    return a / b


def compute(func, a, b):
    print(func)
    return func(a, b)


print(compute(add, 20, 10))
print(compute(subtract, 20, 10))
print(compute(multiply, 20, 10))
print(compute(divide, 20, 10))

运行结果:

f674191bbf46e670e8c4a14e624f9b33.jpeg

4、将函数作为返回值

将函数作为返回值,其实在高阶函数的应用场景中,很是常见,所以我们可以看到一个函数后面写了两个括号或者更多的括号进行多层级的函数调用。

还是四则运算的例子,这次代码写得更怪异,只是为了演示:

from rich.pretty import pprint as print


def compute(func_name):
    def add(a, b):
        return a + b

    def subtract(a, b):
        return a - b

    def multiply(a, b):
        return a * b

    def divide(a, b):
        return a / b


    funcs = {func.__name__: func for func in (add, subtract, multiply, divide)}
    print(funcs)
    return funcs[func_name]


print(compute('add')(20, 10))
# 等价于
add = compute('add')
print(add)
print(add(20, 10))

运行结果:

ccff3c0adfda992a7ee3f827b18a46d9.jpeg

其他编程语言中函数的使用

从上面的代码示例中,由于Python从最开始就是“一切皆对象”的设计理念,所以,函数作为一等公民的特性是一种很自然的状态。

但是,如果有其他编程语言的使用经验,会稍微觉得有些不适用。

比如,在Java中,在Java8之前,函数并没有一等公民的特权,只能通过接口或者匿名类的方式来进行各种模拟的尝试,习惯了函数式编程的同学,会觉得很繁琐而且很拧巴。

需要说明的是,这里并不是要说明编程语言的优劣,也无意引起不同编程语言拥泵的论战,只是不同编程语言设计理念上的差异。不同的编程语言各有其擅场,也各有其更加适用或者相对不太适用的应用场景。

而在C语言中,虽然函数严格意义上,也不是一等公民,但是,由于C语言是相对更加底层的编程语言,指针的特性,使得函数可以像一等公民一样。

比如,函数名实际为函数的内存地址,函数指针可以赋值给变量,可以存储在数组中,也可以作为参数进行传递等。

所以,相对来说,从设计理念的角度来看,Python设计之初就使得函数是作为一等公民存在的,从而在高阶函数、以及函数式编程这些应用领域中,会显得更加灵活、自然。

总结

Python中“一切皆对象”的设计理念,使得函数作为一等公民的存在显得更加自然。在高阶函数处理及函数式编程的场景中,Python相对Java或者C语言等,会显得更加合适一些。

感谢您的拨冗阅读,希望这些内容能对您学习Python有些许帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南宫理的日知录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值