Python函数式编程术语大全!

import inspect
add = lambda a, b: a + b
len(inspect.getfullargspec(add).args)

2

复制代码
Higher-Order Function – 高阶函数

以函数为参数或返回值

Python学习交流群:1004391443,这里是python学习者聚集地,有大牛答疑,有资源共享!有想学习python编程的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。

is_type = lambda type_: lambda x: isinstance(x, type_)
li = [0, ‘1’, 2, None]
[l for l in li if is_type(int)(l)]

[0, 2]

复制代码
Closure – 闭包

闭包是一种在变量作用域之外访问变量的方法。是一种将函数存储在环境中的方法。

闭包是一个作用域,它捕获函数的局部变量以便访问,即使在执行已经移出定义它的块之后也是如此。

add_to = lambda x: lambda y: x + y
add_to_five = add_to(5)
add_to_five(3)

8

复制代码
函数addTo()返回一个函数(内部称为add()),将它存储在名为addToFive的变量中,它带有参数为5的柯里化调用。

理想情况下,当函数addTo完成执行时,其作用域与局部变量add,x,y就变得不可访问。 但是,它在调用addToFive()时返回8。 这意味着即使在代码块完成执行后也会保存函数addTo的状态,否则无法知道addTo被调用为addTo(5)并且x的值被设置为5。

词法作用域范围是它能够找到x和add的值的原因 – 已经完成执行的父项的私有变量。该值称为闭包。

堆栈以及函数的词法范围以对父项的引用形式存储。这可以防止关闭和底层变量被垃圾收集(因为至少有一个对它的实时引用)。

闭包是一种通过引用其主体外部的字段来包围其周围状态的函数。封闭状态保持在闭包的调用之间。

Partial Function – 偏函数

通过对原始函数预设参数来创建一个新的函数

from functools import partial
add3 = lambda a, b, c: a + b + c
five_plus = partial(add3, 2, 3)
five_plus(4)

9

复制代码
Currying – 柯里化

将一个多元函数转变为一元函数的过程

add = lambda a, b: a + b
curried_add = lambda a: lambda b: a + b
curried_add(3)(4)

7

add2 = curried_add(2)
add2(10)

12

复制代码
Auto Currying – 自动柯里化

from toolz import curry
add = lambda a, b: a + b
curried_add = curry(add)
curried_add(1, 2)

3

curried_add(1)(2)

3

curried_add(1)

<function <lambda> at 0x000002088BBD5E18>

复制代码
Function Composition – 函数组合

接收多个函数作为参数,从右到左,一个函数的输入为另一个函数的输出

import math
from functools import reduce

组合2个函数

compose = lambda f, g: lambda a: f(g(a))

组合多个函数

compose = lambda *funcs: reduce(lambda f, g: lambda args: f(g(args)), funcs)
floor_and_to_string = compose(str, math.floor)
floor_and_to_string(12.12)

’12’

复制代码
Purity – 纯函数

输出仅由输入决定,且不产生副作用

greet = lambda name: f’hello, {name}’
greet(‘world’)
‘hello, world’
复制代码
以下代码不是纯函数

情况1:函数依赖全局变量

NAME = ‘alphardex’
greet = lambda: f’hi, {NAME}’
greet()

‘hi, alphardex’

情况2:函数修改了全局变量

greeting = None
def greet(name):
global greeting
greeting = f’hi, {name}’
greet(‘alphardex’)
greeting

‘hi, alphardex’

复制代码
Side effects – 副作用

如果函数与外部可变状态进行交互,则它是有副作用的

最典型的例子是创建日期和IO

from datetime import datetime
different_every_time = datetime.now()
different_every_time

datetime.datetime(2019, 4, 20, 17, 30, 24, 824876)

different_every_time = datetime.now()
different_every_time

datetime.datetime(2019, 4, 20, 17, 31, 41, 204302)

复制代码
Idempotent – 幂等性

如果一个函数执行多次皆返回相同的结果,则它是幂等性的

abs(abs(abs(10)))

10

复制代码
Point-Free Style – Point-Free 风格

定义函数时,不显式地指出函数所带参数,这种风格通常需要柯里化或者高阶函数

Point-Free风格的函数就像平常的赋值,不使用def或者lambda关键词

map_ = lambda func: lambda li: [func(l) for l in li]
add = lambda a: lambda b: a + b
increment_all = map_(add(1))
numbers = [1, 2, 3]
increment_all(numbers)

[2, 3, 4]

复制代码
Predicate – 谓词

根据输入返回 True 或 False。常用于filter函数中

filter函数亦可以用列表推导式的if判断实现

above_two = lambda a: a > 2
li = [1, 2, 3, 4]
[l for l in li if above_two(l)]

[3, 4]

复制代码
Contracts – 契约

契约保证了函数或者表达式在运行时的行为。当违反契约时,将抛出一个错误。

def contract(input):
if isinstance(input, int):
return True
raise Exception(‘Contract Violated: expected int -> int’)
add_one = lambda num: contract(num) and num + 1
add_one(2)

3

add_one(‘hello’)

Exception Traceback

复制代码
Functor – 函子

一个实现了map函数的对象,map会遍历对象中的每个值并生成一个新的对象。

Python中最具代表性的函子就是list, 因为它遵守因子的两个准则

在Python中可以用列表推导式来代表map操作

Preserves identity – 一致性

li = [1, 2, 3]
[l for l in li] == li

True

复制代码
Composable – 组合性

li = [1, 2, 3]
compose = lambda f, g: lambda a: f(g(a))
[compose(str, lambda x: x+1)(l) for l in li]

[‘2’, ‘3’, ‘4’]

[str(l+1) for l in li]

[‘2’, ‘3’, ‘4’]

复制代码
Referential Transparency – 引用透明性

一个表达式能够被它的值替代而不改变程序的行为成为引用透明

greet = lambda: ‘hello, world.’
复制代码
Lazy evaluation – 惰性求值

按需求值机制,只有当需要计算所得值时才会计算

Python中可用生成器实现

import random
def rand():
while True:
yield random.random()
rand_iter = rand()
next(rand())

0.16066473752585098

复制代码
Monoid – 单位半群

一个对象拥有一个函数用来连接相同类型的对象

数值加法是一个简单的Monoid

1 + 1

2

复制代码
以上例子中,数值是对象,而+是函数

以下能更清晰地说明它

from operator import add
type(1)

<class ‘int’>

add(1, 1)

2

复制代码
数值是int类的实例对象,add是实现了加法的函数

与另一个值结合而不会改变它的值必须存在,称为 identity 。

加法的identity值为 0:

1 + 0

1

复制代码
需要满足结合律

1 + (2 + 3) == (1 + 2) + 3

True

复制代码
list的结合也是Monoid

[1, 2].extend([3, 4])
复制代码
identity值为空数组

[1, 2].extend([])
复制代码
identity与compose函数能够组成monoid

identity = lambda a: a
compose = lambda f, g: lambda a: f(g(a))
foo = lambda bar: bar + 1
compose(foo, identity)(1) == compose(identity, foo)(1) == foo(1)

True

复制代码
Monad – 单子

拥有 of 和 chain 函数的对象。 chain 很像 map ,除了用来铺平嵌套数据。

flatten = lambda li: sum(li, [])
of = lambda *args: list(args)
chain = lambda func: lambda li: list(flatten([func(l) for l in li]))
[s.split(‘,’) for s in of(‘cat,dog’, ‘fish,bird’)]

[[‘cat’, ‘dog’], [‘fish’, ‘bird’]]

chain(lambda s: s.split(‘,’))(of(‘cat,dog’, ‘fish,bird’))

[‘cat’, ‘dog’, ‘fish’, ‘bird’]

复制代码
Comonad – 余单子

拥有 extract 与 extend 函数的对象。

class CoIdentity:
def init(self, v):
self.val = v
def extract(self):
return self.val
def extend(self, func):
return CoIdentity(func(self))
CoIdentity(1).extract()
1
from beeprint import pp
pp(CoIdentity(1).extend(lambda x: x.extract() + 1))

instance(CoIdentity):

val: 2

复制代码
Morphism – 态射

一个变形的函数

Endomorphism – 自同态

输入输出是相同类型的函数

uppercase = lambda string: string.upper()
uppercase(‘hello’)

‘HELLO’

decrement = lambda number: number – 1
decrement(2)

1

复制代码
Isomorphism – 同构

不同类型对象的变形,保持结构并且不丢失数据。

例如,一个二维坐标既可以表示为列表 [2, 3] ,也可以表示为字典 {‘x’: 2, ‘y’: 3} 。

pair_to_coords = lambda pair: {‘x’: pair[0], ‘y’: pair[1]}
coords_to_pair = lambda coords: [coords[‘x’], coords[‘y’]]
pair_to_coords(coords_to_pair({‘x’: 1, ‘y’: 2}))

{‘x’: 1, ‘y’: 2}

复制代码
Setoid

拥有 equals 函数的对象。 equals 可以用来和其它对象比较。

Python里的 == 就是 equals 函数

[1, 2] == [1, 2]

True

[1, 2] == [3, 4]

False

复制代码
Semigroup – 半群

拥有 concat 函数的对象。 concat 可以连接相同类型的两个对象。

Python里列表的 extend 就是 concat 函数

li = [1]
li.extend([2])
li

[1, 2]

复制代码
Foldable

一个拥有 reduce 函数的对象。 reduce 可以把一种类型的对象转化为另一种类型。

from functools import reduce
sum_ = lambda li: reduce(lambda acc, val: acc + val, li, 0)
sum_([1, 2, 3])
6
复制代码
Type Signatures – 类型签名

通常可以在注释中指出参数与返回值的类型

add :: int -> int -> int

add = lambda x: lambda y: x + y

increment :: int -> int

increment = lambda x: x + 1
复制代码
如果函数的参数也是函数,那么这个函数需要用括号括起来

call :: (a -> b) -> a -> b

call = lambda func: lambda x: func(x)
复制代码
字符a, b, c, d表明参数可以是任意类型。以下版本的 map 的参数func,把一种类型a的数组转化为另一种类型b的数组

map :: (a -> b) -> [a] -> [b]

map_ = lambda func: lambda li: [func(l) for l in li]
复制代码

    原文作者:不谈风月_0eb8
    原文地址: https://www.jianshu.com/p/617f51c01661
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞