惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Microsoft Azure Blog
Microsoft Azure Blog
人人都是产品经理
人人都是产品经理
博客园 - 聂微东
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
V
V2EX
小众软件
小众软件
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Hackread – Cybersecurity News, Data Breaches, AI and More
量子位
Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
宝玉的分享
宝玉的分享
有赞技术团队
有赞技术团队
J
Java Code Geeks
WordPress大学
WordPress大学
The Cloudflare Blog

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率
Python 函数式编程
音视频开发进阶 · 2017-12-22 · via 音视频开发进阶

一个专注音视频领域的小圈子

函数式编程是一种编程范式,不同于之前的面向对象编程。它是面向数学的抽象,也就是说,这里的函数二字不再是我们编程语言中的函数,而是数学中的函数了。 在数学中,y = f(x) ,则因变量 y 是自变量 x 的函数,则 f(x) 是 x 的函数。在这里,f() 只是数学中的一个式子,它对应的就是编程语言中的函数。而 f(x) 对应编程语言中函数执行完的结果。

所以,当我们说到函数式编程时,要把这个函数理解成数学中的函数,它就是 f(x) 。而在数学中,f(x) 可不是一个具体的数值,它也是要计算的(不然哪来的数学考试)。

明确了函数的概念后,就很方便理解函数式编程了。

比如,我们有一个函数 y = x + 1 ,就可以编写如下代码:

def func(x):
	return x + 1 

此时,假设要求当 x = 2 时 y 的值,那么 y = func(2) ,这就是一个很简单的函数式编程了。

函数式编程的特点

在函数式语言中,函数是作为一等公民存在的。函数可以在任何地方定义,在函数内或者函数外;函数可以作为函数的参数和返回值,可以对函数进行组合。

函数式编程具有如下的特点:

变量的不可变性

每个函数的执行都不会改变外部的数据,而是在函数内部返回一个新的值。这个比较好理解,我们的 f(x) 返回的是 y 而不改变 x 的值。

纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数称之为没有副作用的。

函数也可以当做变量

一个函数 f(x) 也可以当做变量来使用。假设 y = f(x) ,那么 y 就是一个变量,并且它还是个函数,想要执行函数的运算操作,调用 y() 即可。这样就可以实现惰性求值。

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。

在 Python 中,函数也是可以当做变量的。

尾递归优化

由于递归调用是非常消耗内存的,尤其是递归深度很深时,容易发生栈溢出。这是因为函数调用会在内存形成一个调用帧,保存调用位置和调用记录等信息。

假如我们在函数 A 的内部调用函数 B,那么在 A 的调用记录上会形成一个 B 的调用记录,如果在 B 的内部还调用了函数 C ,那么还有一个 C 的调用记录。

假如使用尾调用,即:在函数的最后一步调用另一个函数。那么我们就不需要保存外层函数的调用记录了,直接用内层函数的调用记录覆盖外层即可。

如果所有的函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,节省了内存。

利用尾调用优化,我们就可以在递归操作时,使用尾递归优化,确保函数的最后一步操作是调用了函数自身。

高阶函数

函数式编程还有特性就是高阶函数。

高阶函数就是参数为函数或返回值为函数的函数。

在 Python 中也提供了 mapreducefiltersorted 高阶函数。

map 用法

map() 函数接收两个参数,一个是函数,一个是 Iterable,map 将传入的函数依次作用到序列的每个元素,并把结果作为新的 Iterable 返回。

def f(x):
    return x + 1
data = [1,2,3,4]
r = map(f,data)
print(list(r))

####reduce 用法

reduce() 把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce 把结果继续和序列的下一个元素做累积计算。

from functools import reduce

def f(x,y):
    return  x*y

data = [1,2,3,4]
r = reduce(f,data)

print(r)

filter 用法

filter() 函数用于过滤序列,filter 函数把传入的函数依次作用于每个元素,返回根据返回的是 True 还是 False 决定保留还是丢弃该元素。

def is_odd(n):
    return n % 2 == 1

result  = filter(is_odd,[1,2,3,4,5])

print(list(result))

sorted 用法

sorted() 也是一个高阶函数,接收一个函数来实现自定义的排序。

例如按绝对值排序代码:

print(sorted([-34,5,-2,43],key=abs))

闭包

闭包是那些带着它们被定义时的环境的函数。特别的,一个闭包可以引用它定义时存在的变量。

def func(x):
    def f():
        return  x + 1
    return f

result = func(1)

print(type(result))

print(result())

闭包的特点:返回的函数还引用了外层函数的局部变量,所以,要正确的使用闭包,就要确保返回函数不用引用任何循环变量,或者后续会发生变化的变量,否则,闭包所持有的外层函数的局部变量将会是最后一次改变时的值。

参考

  1. http://coolshell.cn/articles/10822.html
  2. https://www.zhihu.com/question/28292740
  3. http://www.ruanyifeng.com/blog/2015/04/tail-call.html
  4. http://www.liaoxuefeng.com/

原创文章,转载请注明来源:    Python 函数式编程