Python函数式编程实战:从面向过程到函数式的演进与纯函数解析

Mason
Mason
发布时间:2026-10-12 | 3人浏览过
原创

本文深入解析Python中的函数式编程特性,对比面向过程与面向对象写法,详解map、filter、reduce等核心高阶函数及生成器表达式。通过具体案例演示递归与Lambda表达式的应用,并阐述纯函数、延迟计算及类型提示在提升代码质量中的作用,帮助开发者掌握函数式编程的核心思想与落地技巧。

Python函数式编程

Python并非纯粹的函数式编程语言,但开发者完全可以利用其特性进行函数式编程风格的开发。

简而言之,Python具备支持函数式编程的语言特性,允许开发者采用函数式的思维模式进行编码。

因此,可以借鉴函数式语言的设计模式与编程技术,将代码重构为符合函数式编程规范的形式。

通常情况下,函数式代码因其简洁性和优雅性而备受推崇。

以上是对函数式编程优势的简要概述。

接下来探讨在Python中具体有哪些适合函数式编程的技术点,以及哪些特性可能构成限制。

我们将分析其适用场景与不足之处。

以下两点内容供初步了解,建立直观印象即可。

优点方面,生成器表达式是重点,后文会多次提及;此外Python内置了丰富的高阶函数,其中reduce、map和filter被称为三大核心函数。

缺点方面,Python不支持无限递归等某些函数式语言特有的机制。

若搜索“什么是函数式编程”,多数资料会给出标准定义。

函数式编程允许将函数本身作为参数传递给另一个函数,同时也允许函数返回另一个函数。

这一定义准确概括了函数式编程的核心特征。

实质上,函数式编程是在函数中定义表达式并实现其逻辑,即通过函数来承载和执行业务代码。

这看似是常识,但函数式编程还有一个关键补充:必须避免状态变化和可变对象的使用。

其中,避免状态变化的重点在于关注赋值语句及其对状态的影响,因此在严格的函数式编程中,不应出现global或nolocal等关键字。

通过同一案例的不同实现方式,展示函数式编程的具体应用。

概念与原理较为抽象,此处减少理论阐述,直接通过源码差异进行对比展示。

案例目标:计算1到100之间所有能被5或7整除的数字之和。

面向过程的实现方式

count = 0
for num in range(1, 101):
    if num % 5 == 0 or num % 7 == 0:
        count += num
print(count)

在面向过程的写法中,逻辑按顺序从上至下执行,例如num变量从1遍历到100,若对5或7取余结果为0,则表明可整除,随后将count累加器与对应的num数值相加,最终得到总和。

这种思路属于典型的面向过程编程,通常是初学者最先掌握的编程方式。

面向对象的实现方式

该写法包含两种路径:一是使用Python内置列表实现,二是自定义类来实现。

第一种写法示例如下:

count = list()
for num in range(1, 101):
    if num % 5 == 0 or num % 7 == 0:
        count.append(num)
print(sum(count))

在上述代码中,变量count被声明为list类型,即列表对象,但整体结构仍带有过程式编程的痕迹。

例如末尾使用sum(count)的方式显得较为突兀,未能充分体现面向对象的设计思想。

接下来,我们创建一个自定义类来实现逻辑。

class My_List_Sum(list):
    def sum(self):
        count = 0
        for n in self:
            count += n
        return count
count = My_List_Sum()
for num in range(1, 101):
    if num % 5 == 0 or num % 7 == 0:
        count.append(num)
print(count.sum())

上述代码中,我们自定义了一个My_List_Sum类,使其继承自list,此时应明确,list即为类名,并在类内部实现了sum方法,随后调用该对象的sum方法,从而完整应用了面向对象的设计模式。

接下来进入核心主题:函数式编程的具体落地实现。

在正式编码前,需回顾基础知识,包括lambda表达式及列表相加操作。

判断一个数字是否为5或7的倍数,使用lambda的写法如下:

multiple = lambda x: x % 5 == 0 or x % 7 == 0
a = multiple(3) # False
b = multiple(5) # True
c = multiple(7) # False
print(a, b, c)

列表相加的代码示例如下:

print([1]+[2]) # [1,2]

基于上述知识,可以编写一个递归函数来实现相应逻辑,代码说明已添加至注释中。

def tool(n: int, end: int, filter_func) -> list:
    """返回一个筛选之后的列表
    :param n: 起始值
    :param end: 终止值
    :param filter_func: 判断表达式
    """
    # 如果到达上限,直接返回空列表
    if n == end: return []
    # 如果满足过滤条件,返回该值与下一个值组成的列表
    if filter_func(n):
        return [n] + tool(n + 1, end, filter_func)
    else:
        # 不满足过滤条件,直接返回下一个值
        return tool(n + 1, end, filter_func)
# 测试代码
ret = tool(1, 101, lambda x: x % 5 == 0 or x % 7 == 0)
print(ret)
print(sum(ret))

上述代码即为求和功能的函数式实现,其中部分逻辑解析如下:

  • 设定初始值与上限值,当迭代值等于上限值时,返回空列表,表示递归结束;
  • 传入一个判断条件,本案例中使用lambda表达式,用于筛选5和7的倍数;
  • 当满足条件时,执行相加与迭代操作;若不满足条件,则直接进入下一次迭代。

此外,还存在另一种函数式编程的写法,代码如下:

print(sum(n for n in range(1, 101) if n % 5 == 0 or n % 7 == 0))

此处使用的生成器将在后文中详细展开说明。

Python函数式编程的核心特点

在Python中,函数被视为对象,例如声明一个函数后,可以调用其相关属性。

下述代码展示了函数对象的属性,其余内容可自行测试验证。

def my_func(var1, var2, **kw):
    return var1 + var2
print(type(my_func))  # <class 'function'>
print(my_func.__code__)
print(my_func.__dict__)
print(my_func.__code__.co_code)
print(my_func.__code__.co_filename)
print(my_func.__code__.co_argcount)

函数式编程高效的原因之一是延迟计算,也称为惰性求值,这些概念将在后文逐步展开,目前先建立初步印象。

正是因为函数即对象,才构成了本文开篇对函数式编程的定义基础。

函数可以接受其他函数作为参数,或返回另一个函数,因此在实际编码中,我们将函数视为其他语言中的“对象”,从而实现函数式编程。

接下来接触Python中的纯函数概念及其实际应用。

纯函数

纯函数是一个重要概念,指函数不对函数外部的作用域产生影响,即其作用域仅限于本地。

简单来说,即在函数内部避免赋值操作,同时应避免使用类似global等关键字。

针对此要求,lambda表达式符合纯函数的定义。

首先查看一个纯函数的示例:

def my_func(num: int) -> int:
    return num * 100

上述代码中函数的返回值仅与num参数有关,需满足以下两个条件:

  • 不修改全局变量;
  • 不更新可变数据结构,如列表或字典。

了解纯函数概念后,下面介绍函数作为对象的具体应用。

在Python中声明一个类时,默认会携带部分内置方法,例如:

from typing import Callable
# 声明一个类,该类无意义,仅测试使用
class Ext:
    # 传入的函数,可携带1~2个参数
    def __init__(self, test_demo: Callable[[int], int]) -> None:
        self.func = test_demo
    # 返回结果扩大2倍
    def __call__(self, arg: int) -> int:
        return self.func(arg) * 2
def one_func(var):
    return var + 1
def two_func(var):
    return var * 3
def three_func(var):
    return var
a = Ext(one_func)
print(a(3))  # 8
b = Ext(two_func)
print(b(3))  # 18
c = Ext(three_func)
print(c(3))  # 6

上述代码使用了一个新模块typing,该模块在Python 3.5之后引入,主要用于为Python提供静态类型检查功能。

本案例中导入的是回调函数Callable,其格式如下:

Callable[[Arg1Type, Arg2Type],ReturnType]

其中内部方括号Arg1Type表示参数类型,ReturnType表示返回值类型。

上述三个函数的签名均与Callable定义一致,因此均可作为test_demo参数的值进行传递。

以上即为Python函数式编程中面向过程、面向对象及函数式风格的简要分析,更多关于Python函数式编程的资料请关注本站其他相关文章。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表