如何制作函数作曲家
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)
正如我在评论中所说,这是一个实现组合的示例。在数学上,组合很简单,因为数学函数总是接受一个参数并返回一个参数。因此,f
和 g
两个函数的组合总是可以简单地定义为
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
【讨论】:
以上是关于如何制作函数作曲家的主要内容,如果未能解决你的问题,请参考以下文章