Python函数式编程术语大全!

作者: 14e61d025165 | 来源:发表于2019-05-02 15:20 被阅读0次

    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]
    复制代码

    相关文章

      网友评论

        本文标题:Python函数式编程术语大全!

        本文链接:https://www.haomeiwen.com/subject/sapnnqtx.html