如何制作函数作曲家

Posted

技术标签:

【中文标题】如何制作函数作曲家【英文标题】:How to make a function composer 【发布时间】:2019-04-11 04:19:18 【问题描述】:

我正在尝试为我的大学学位创建一个围绕其他函数的函数。例如我想打电话给round_sqrt = round(sqrt) 当我拨打round_sqrt(5) 时,它必须显示2 而不是2.23606797749979。我正在尝试的是:

def rounding(funct):
    return round(funct)

但这不起作用。

编辑:函数应该只有一个参数。例如 函数的开头应该是

def rounding(func):

所以在这个函数中,funct 函数需要四舍五入。 所以当我打电话给rounding(abs)(3.2) 时,它会告诉我3

【问题讨论】:

您正在寻找功能组合。在数学上,h = f ∘ g 定义为h(x) = f(g(x))。虽然如果 Python 可以在 Python 中使用组合运算符会很好,但实际问题需要您自己定义组合函数。 玩作曲是我很快爱上(然后讨厌,然后爱上,然后讨厌,然后......)Haskell的原因之一。 Haskell 很简单,因为一切都符合理论上合理的数学框架。 Haskell 很难,因为我们不习惯遵守上述框架。 :) 您可以留下问题以帮助其他人或将其删除,但请不要只删除所有内容。 @AdamSmith 听起来你在作曲hate . love . hate . love 【参考方案1】:

你应该检查闭包:

def rounder(func):
    def inner(*args, **kwargs):
        return round(func(*args, **kwargs))
    return inner

然后你可以使用@ 字符来装饰函数:

@rounder
def adder(x, y):
    return x + y

print(adder(1.1, 2.2))

输出3

补充:

    您可以在闭包中使用functools.wraps,这样您就不会丢失有关原始函数的信息(例如文档字符串、函数名称)。 您可以通过 Google 搜索这些术语找到大量资源,用于了解闭包(例如 1、2)和装饰器(例如 1、2)。

【讨论】:

嘿,装饰师! 我什么都听不懂。我认为答案应该更容易 @phpkubrick 什么?它是 3 行代码和一个函数头?你想要简单多少?你提到你在上大学——你可以理解这一点。 我无法理解 *args、**kwargs @phpkubrick 我想那是你应该做的下一点研究,因为它们在 Python 中被到处使用,而且非常有用。 ***.com/questions/36901/…【参考方案2】:

对于你的具体例子,你可以写

def round_sqrt(x):
    return round(sqrt(x))

Alex's answer 概括了这一点;他为您定义了一个创建 round_sqrt 的函数。如果函数已经定义,你只需将它作为参数传递给rounder

round_sqrt = rounder(sqrt)

当然,如果您不想定义round_sqrt,则无需定义。 rounder(sqrt)(3.2) 可以直接调用,但如果您希望多次使用 rounder 的返回值而不是每次都重新定义它,那么保护它的返回值要高效得多。

否则,装饰器语法只是简写(使用 Alex 的示例)

def adder(x, y):
    return x + y

adder = rounder(adder)

正如我在评论中所说,这是一个实现组合的示例。在数学上,组合很简单,因为数学函数总是接受一个参数并返回一个参数。因此,fg 两个函数的组合总是可以简单地定义为

def compose(f, g):
    def h(x):   # The name doesn't matter
        return f(g(x))
    return h

然后

round_sqrt = compose(round, sqrt)

(忽略围绕实现的各种实际问题,理论上 Python 甚至可以为函数提供 Unicode 运算符 round_sqrt = round ∘ sort。解释为什么这不会发生超出了这个答案的范围。)

不过,在 Python 中,函数要复杂得多。它们可以接受多个参数,可以接受任意数量的参数和任意关键字参数,虽然每个参数在技术上都返回一个值,但该值可以是一个被认为是多个值的元组或 dict。因此,您可能希望通过多种方式将g 的返回值传递给函数f,而不是简单的compose 函数。

【讨论】:

不应该return f(g(z))return f(g(x)) 是的,我不知道z来自哪里。 compose 中使用 lambda 不是更干净吗? 我发现def 在可以使用时更加清晰。【参考方案3】:

Python 本身不支持函数组合。您可以按照@Alex's solution 使用装饰器。您可以按照@chepner's solution 明确定义一个新函数。

或者您可以使用第 3 方库。例如,通过toolz.compose

from toolz import compose

def adder(x, y):
    return x + y

round_adder = compose(round, adder)

round_adder(1.1, 2.2)  # 3

【讨论】:

以上是关于如何制作函数作曲家的主要内容,如果未能解决你的问题,请参考以下文章

调用未定义函数 get():作曲家

如何在 intelephense 中定义一个未定义的函数(在 VSCode 中)?

覆盖 laravel 5 辅助函数

laravel 4 视图,在哪里放置基于类的作曲家

在 laravel 中加载作曲家类

在laravel中加载一个作曲家类