这是什么功能范式

Chr*_*rno 1 python functional-programming

我正在编写一些 python 代码,并且正在实现一种我已经用多种语言反复完成的模式。我一直认为这是某种功能范例,并且可以在功能上实现(不使用循环for),但我没有看到它。Map获取一个系列并返回一个新系列。Reduce获取一系列结果并将其简化为单个结果。这两者都不是。

下面这个函数的想法是对单个字符串重复应用转换。在这种情况下:

  1. 替换所有uuid
  2. 然后替换5-9位之间的所有数字组
  3. 将会有更多的转变
def to_template(message):
    mappers = [
        ('[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', '{.uuid}'),
        (' [0-9]{5,9}.', ' {.request_id}.')
    ]
    result = message
    for pattern, replacement in mappers:
        result = re.sub(pattern, replacement, result)

    return result
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 这个可以从功能上实现吗?
  2. 是否有一个已知的功能范例?

che*_*ner 5

在函数式编程术语中,这是折叠:您将替换操作列表折叠(即减少)为单个字符串,并以字符串作为起点。

在 Python 中,您可以使用模块reduce中的函数来编写此代码functools

from functools import reduce


def to_template(message):
    mappers = [ ... ]
    return reduce(lambda r, p: re.sub(*p, r), mappers, message)
Run Code Online (Sandbox Code Playgroud)

reducere.sub使用 from 的元素mappers作为第一个参数并使用上一次调用的结果作为第二个参数重复调用。(第一次调用用作message的“第 0 个”返回值re.sub。)


递归地,可以实现reduce

def reduce(f, itr, init):
    if not itr:
        return init
    else:
        return reduce(f, itr[1:], f(init, itr[0]))
Run Code Online (Sandbox Code Playgroud)

迭代地,它看起来很像你的函数:

def reduce(f, itr, init):
    result = init
    for x in itr:
        result = f(result, x)
    return result
Run Code Online (Sandbox Code Playgroud)

从理论上讲,您还可以想象使用函数组合将函数列表折叠成单个函数,然后应用于您的消息。

from functools import reduce, partial


def to_template(message):
    mappers = [
        partial(re.sub, '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', '{.uuid}'),
        partial(re.sub, ' [0-9]{5,9}.', ' {.request_id}.')
    ]

    # Apply f first, so that reduce applies functions
    # in the order they appear in the list.
    def compose(f, g):
        return lambda x: g(f(x))

    def identity(x):
        return x

    f = reduce(compose, mappers, identity)
    return f(message)
Run Code Online (Sandbox Code Playgroud)

但是,对于大量映射操作,您可能会通过reducecompose构建的嵌套函数调用达到递归限制。