​​​​​​​Python 入门学习之函数式编程

目录
  • 前言
  • 把函数作为对象
  • 把对象作为函数
  • 数据结构内的函数
  • 把函数作为参数和返回值
  • 嵌套函数
  • 单表达式函数(Lambda 表达式)
  • Map、Filter 和 Reduce
    • Map
    • Filter
    • Reduce

前言

本文对 Python 中的函数式编程技术进行了简单的入门介绍。

在 Python 中,函数是「头等公民」(first-class)。也就是说,函数与其他数据类型(如 int)处于平等地位。

因而,我们可以将函数赋值给变量,也可以将其作为参数传入其他函数,将它们存储在其他数据结构(如 dicts)中,并将它们作为其他函数的返回值。

把函数作为对象

由于其他数据类型(如 string、list 和 int)都是对象,那么函数也是 Python 中的对象。我们来看示例函数 foo,它将自己的名称打印出来:

def foo():
   print("foo")

由于函数是对象,因此我们可以将函数 foo 赋值给任意变量,然后调用该变量。

例如,我们可以将函数赋值给变量 bar:

bar = foo
bar()
#will print "foo" to the console

语句 bar = foo 将函数 foo 引用的对象赋值给变量 bar。

把对象作为函数

当对象可调用时(callable),它们与函数一样,如 object()。这是通过 call 方法实现的。

示例如下:

class Greeter:
   def __init__(self, greeting):
      self.greeting = greeting
   def __call__(self, name):
      return self.greeting + " " + name

每一次配置 Greeter 类的对象时,我们都会创建一个新的对象,即打招呼时可以喊的新名字。

如下所示:

morning = Greeter("good morning") #creates the callable object
morning("john") # calling the object
#prints "good morning john" to the console

我们可以调用 morning 对象的原因在于,我们已经在类定义中使用了 call 方法。为了检查对象是否可调用,我们使用内置函数 callable:

callable(morning) #true
callable(145) #false. int is not callable. 

数据结构内的函数

函数和其他对象一样,可以存储在数据结构内部。例如,我们可以创建 int to func 的字典。当 int 是待执行步骤的简写时,这就会派上用场。

# store in dictionary
mapping = {
   0 : foo,
   1 : bar
}
x = input() #get integer value from user
mapping[x]() #call the func returned by dictionary access

类似地,函数也可以存储在多种其他数据结构中。

把函数作为参数和返回值

函数还可以作为其他函数的参数和返回值。接受函数作为输入或返回函数的函数叫做高阶函数,它是函数式编程的重要组成部分。

高阶函数具备强大的能力。就像《Eloquent JavaScript》中解释的那样:

「高阶函数允许我们对动作执行抽象,而不只是抽象数值。」

我们来看一个例子。假设我们想对一个项目列表(list of items)执行迭代,并将其顺序打印出来。我们可以轻松构建一个 iterate 函数:

def iterate(list_of_items):
    for item in list_of_items:
        print(item)

看起来很酷吧,但这只不过是一级抽象而已。如果我们想在对列表执行迭代时进行打印以外的其他操作要怎么做呢?

这就是高阶函数存在的意义。我们可以创建函数 iterate_custom,待执行迭代的列表和要对每个项应用的函数都是 iterate_custom 函数的输入:

def iterate_custom(list_of_items, custom_func):
   for item in list_of_items:
        custom_func(item)

这看起来微不足道,但其实非常强大。

我们已经把抽象的级别提高了一层,使代码具备更强的可重用性。现在,我们不仅可以在打印列表时调用该函数,还可以对涉及序列迭代的列表执行任意操作。

函数还能被返回,从而使事情变得更加简单。就像我们在 dict 中存储函数一样,我们还可以将函数作为控制语句,来决定适合的函数。

例如:

def add(x, y):
    return x + y
def sub(x, y):
    return x - y
def mult(x, y):
    return x * y
def calculator(opcode):
    if opcode == 1:
       return add
    elif opcode == 2:
       return sub
    else:
       return mult 
my_calc = calculator(2) #my calc is a subtractor
my_calc(5, 4) #returns 5 - 4 = 1 
my_calc = calculator(9) #my calc is now a multiplier
my_calc(5, 4) #returns 5 x 4 = 20. 

嵌套函数

函数还可以在其他函数内部,这就是「内部函数」。内部函数在创建辅助函数时非常有用,辅助函数即作为子模块来支持主函数的小型可重用函数。

在问题需要特定函数定义(参数类型或顺序)时,我们可以使用辅助函数。这种不遵循传统做法的操作使得解决问题变得更加简单。

假设你想定义一个斐波那契函数 fib(n),该函数只有一个参数 n,我们必须返回第 n 个斐波那契数。

定义此类函数的一种可行方式是:使用辅助函数来追踪斐波那契数列的前两个项(因为斐波那契数是前两个数之和)。

def fib(n):
    def fib_helper(fk1, fk, k):
        if n == k:
           return fk
        else:
           return fib_helper(fk, fk1+fk, k+1)
    if n <= 1:
       return n
    else:
       return fib_helper(0, 1, 1)

将该计算从函数主体移到函数参数,这具备非常强大的力量。因为它减少了递归方法中可能出现的冗余计算。

单表达式函数(Lambda 表达式)

如果我们想在未给函数命名之前写一个函数要怎么做?如果我们想写一个简短的单行函数(如上述示例中的函数 foo 或 mult)要怎么做?

我们可以在 Python 中使用 lambda 关键字来定义此类函数。

示例如下:

mult = lambda x, y: x * y
mult(1, 2) #returns 2

该 mult 函数的行为与使用传统 def 关键字定义函数的行为相同。

注意:lambda 函数必须为单行,且不能包含程序员写的返回语句。

事实上,它们通常具备隐式的返回语句(在上面的示例中,函数想表达 return x * y,不过我们省略了 lambda 函数中的显式返回语句)。

lambda 函数更加强大和精准,因为我们还可以构建匿名函数(即没有名称的函数):

(lambda x, y: x * y)(9, 10) #returns 90

当我们只需要一次性使用某函数时,这种方法非常方便。例如,当我们想填充字典时:

import collections
pre_fill = collections.defaultdict(lambda: (0, 0))
#all dictionary keys and values are set to 0

接下来我们来看 Map、Filter 和 Reduce,以更多地了解 lambda。

Map、Filter 和 Reduce

Map

map 函数基于指定过程(函数)将输入集转换为另一个集合。这类似于上文提到的 iterate_custom 函数。

例如:

def multiply_by_four(x):
    return x * 4
scores = [3, 6, 8, 3, 5, 7]
modified_scores = list(map(multiply_by_four, scores))
#modified scores is now [12, 24, 32, 12, 20, 28]

在 Python 3 中,map 函数返回的 map 对象可被类型转换为 list,以方便使用。现在,我们无需显式地定义 multiply_by_four 函数,而是定义 lambda 表达式:

modified_scores = list(map(lambda x: 4 * x, scores))

当我们想对集合内的所有值执行某项操作时,map 函数很有用。

Filter

就像名称所显示的那样,filter 函数可以帮助筛除不想要的项。例如,我们想要去除 scores 中的奇数,那么我们可以使用 filter:

even_scores = list(filter(lambda x: True if (x % 2 == 0) else False, scores))
#even_scores = [6, 8]

由于提供给 filter 的函数是逐个决定是否接受每一个项的,因此该函数必须返回 bool 值,且该函数必须是一元函数(即只使用一个输入参数)。

Reduce

reduce 函数用于「总结」或「概述」数据集。例如,如果我们想要计算所有分数的总和,就可以使用 reduce:

sum_scores = reduce((lambda x, y: x + y), scores)
#sum_scores = 32

这要比写循环语句简单多了。注意:提供给 reduce 的函数需要两个参数:一个表示正在接受检查的项,另一个表示所用运算的累积结果。

到此这篇关于Python 入门学习之函数式编程的文章就介绍到这了,更多相关Python 函数式编程 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解Python函数式编程之装饰器

    目录 一.装饰器的本质: 函数闭包(functionclosure): 二.装饰器使用方法: 保留函数参数和返回值的函数闭包: 三.多个装饰器的执行顺序: 四.创建带参数的装饰器: 总结 一.装饰器的本质: 装饰器(decorator)本质是函数闭包(function closure)的语法糖(Syntactic sugar) 函数闭包(function closure): 函数闭包是函数式语言(函数是一等公民,可作为变量使用)中的术语.函数闭包:一个函数,其参数和返回值都是函数,用于增强函数功

  • Python函数式编程中itertools模块详解

    目录 容器与可迭代对象 count() 函数 cycle 函数 repeat 函数 enumerate 函数,添加序号 accumulate 函数 chain 与 groupby 函数 zip_longest 与 zip tee 函数 compress 函数 islice.dropwhile.takewhile.filterfalse.filter 总结 容器与可迭代对象 在正式开始前先补充一些基本概念在 Python 中存在容器 与 可迭代对象 容器:用来存储多个元素的数据结构,例如 列表,元

  • Python函数式编程实现登录注册功能

    本文实例为大家分享了Python函数式编程实现登录注册功能的具体代码,供大家参考,具体内容如下 代码: def login(username, password):     """     用于用户登录     :param username:用户输入的用户名      :param password: 用户输入的密码     :return: true表示登录成功,false登录失败     """     # 打开文件     f = ope

  • 浅谈Python 函数式编程

    匿名函数lambda表达式 什么是匿名函数? 匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑.lambda 本质上是一个函数对象,可以将其赋值给另一个变量,再由该变量来调用函数,也可以直接使用. #平时,我们是先定义函数,再进行调用 def power(x): return x ** 2 print(power(2)) #使用lambda表达式的时候,我们可以这样操作 power = lambda x : x **

  • ​​​​​​​Python 入门学习之函数式编程

    目录 前言 把函数作为对象 把对象作为函数 数据结构内的函数 把函数作为参数和返回值 嵌套函数 单表达式函数(Lambda 表达式) Map.Filter 和 Reduce Map Filter Reduce 前言 本文对 Python 中的函数式编程技术进行了简单的入门介绍. 在 Python 中,函数是「头等公民」(first-class).也就是说,函数与其他数据类型(如 int)处于平等地位. 因而,我们可以将函数赋值给变量,也可以将其作为参数传入其他函数,将它们存储在其他数据结构(如

  • python入门学习关于for else的特殊特性讲解

    目录 For-Else 特性的基础知识 使用 For-Else 特性的三个场景 1. 迭代并查找没有标志变量的项 2. 帮助打破嵌套循环 3. 帮助处理异常 总结 不管我们使用哪种编程语言,我们都会写"if-else"语句,但是"for-else"怎么样呢? 对于许多语言,例如 c. c + + 和 Java,如果在循环之后使用"else",那是完全错误的.然而,Python 作为一种优雅的语言,有这种奇怪但有用的特性.如果我们正确地使用它,我们

  • Python入门学习之类的相关知识总结

    前言 Python是面向对象的程序设计(Object Oriented Programming). 面向对象的程序设计的一条基本原则是: 计算机程序由多个能够起到子程序作用的单元或者对象组合而成. 面向对象的程序设计的一个关键性概念是: 数据以及数据的操作(即函数方法)封装在一起. 这个概念对于接触C++的我来说已经很熟悉了.就是"类"Class. Python完全支持所有面向对象的基本功能,比如: "封装"."继承"."多态"

  • Python入门学习Python流处理过程

    目录 Faust是一个流处理库 将kafka流中的思想移植到Python中 agent是一个async def的函数,因此它还可以异步执行其他操作 使用Kafka topic作为"预写日志" Faust支持任何类型的流数据 Faust是静态类型的 Faust简介 高可用性 分布式的 快速 灵活性 安装 绑定 下载并从源文件中安装 使用开发版本 常见问题 Faust是一个流处理库 将kafka流中的思想移植到Python中 它被用于Robinhood去构建高性能的分布式系统和实时数据通道

  • Python入门学习之Python流处理过程

    目录 Faust简介 高可用性 分布式的 快速 灵活性 安装 绑定 下载并从源文件中安装 使用开发版本 常见问题 Faust是一个流处理库,将kafka流中的思想移植到Python中 它被用于Robinhood去构建高性能的分布式系统和实时数据通道,每天处理数十亿的数据. Faust同时提供流处理和事件处理同类型的工具分享例如:Kafka Streams, Apache Spark/Storm/Samza/Flink 它不需要使用一个DSL,仅需要用到Python!这意味着你在做流处理的时候可以

  • python入门学习之自带help功能初步使用示例

    目录 python help使用 modules keywords symbols python help使用 C:\Users\wusong>python Python 3.8.2rc1 (tags/v3.8.2rc1:8623e68, Feb 11 2020, 10:46:21) [MSC v.1916 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or &qu

  • 用Python进行基础的函数式编程的教程

    许多函数式文章讲述的是组合,流水线和高阶函数这样的抽象函数式技术.本文不同,它展示了人们每天编写的命令式,非函数式代码示例,以及将这些示例转换为函数式风格. 文章的第一部分将一些短小的数据转换循环重写成函数式的maps和reduces.第二部分选取长一点的循环,把他们分解成单元,然后把每个单元改成函数式的.第三部分选取一个很长的连续数据转换循环,然后把它分解成函数式流水线. 示例都是用Python写的,因为很多人觉得Python易读.为了证明函数式技术对许多语言来说都相同,许多示例避免使用Pyt

  • Python入门学习指南分享

    对于初学者,入门至关重要,这关系到初学者是从入门到精通还是从入门到放弃.以下是结合Python的学习经验,整理出的一条学习路径,主要有四个阶段 NO.1 新手入门阶段,学习基础知识 总体来讲,找一本靠谱的书,由浅入深,边看边练. 网上的学习教程有很多,多到不知道如何选择.所有教程在基础知识介绍方面都差不多,区别在于讲的是否足够细(例如运行原理)以及是否有足够的练习.目前推荐大家看书<Python编程 从入门到实践> ,作者是美国教师,内容从基础知识开始,循序渐进,层层深入,适合零基础者.课程内

  • Python装饰器的函数式编程详解

    Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然好像,他们要干的事都很相似--都是想要对一个已有的模块做一些"修饰工作",所谓修饰工作就是想给现有的模块加上一些小装饰(一些小功能,这些小功能可能好多模块都会用到),但又不让这个小装饰(小功能)侵入到原有的模块中的代码里去.但是OO的Decorator简直就是一场恶梦,不信你就去看看wikipedia上的词条

  • Python入门学习之字符串与比较运算符

    Python字符串 字符串或串(String)是由数字.字母.下划线组成的一串字符. 一般记为 : s="a1a2···an"(n>=0) 它是编程语言中表示文本的数据类型. python的字串列表有2种取值顺序: 从左到右索引默认0开始的,最大范围是字符串长度少1 从右到左索引默认-1开始的,最大范围是字符串开头 如果你的实要取得一段子串的话,可以用到变量[头下标:尾下标],就可以截取相应的字符串,其中下标是从0开始算起,可以是正数或负数,下标可以为空表示取到头或尾. 比如:

随机推荐