【问题标题】:Is there a better way than this to write Python functions that "depend on parameters"?有没有比这更好的方法来编写“依赖参数”的 Python 函数?
【发布时间】:2020-04-05 04:06:25
【问题描述】:

考虑如下定义的Python函数line

def line(m, b):
    def inner_function(x):
        return m * x + b
    return inner_function

这个函数的属性是对于任何浮点数mb,对象line(m, b)是一个Python函数,当line(m, b)在一个浮点数x上被调用时,它返回一个浮点数@987654329 @。浮点line(m, b)(x) 可以解释为斜率m 和y 截距b 在点x 处的值。这是编写“取决于参数”mb 的 Python 函数的一种方法。

  1. 这种编写依赖于某些参数的 Python 函数的方法是否有特殊名称?
  2. 是否有更 Pythonic 和/或计算效率更高的方法来编写与上述 line 执行相同操作的函数?

【问题讨论】:

  • 这不是“Pythonic”怎么办?效率不高怎么办?
  • 这些被称为closures - 它们很常见、有用并且完全可以写出来。
  • 你可以写一个单行:line = lambda m, b: lambda x: m * x + b,但是你的代码无论如何都很好(“pythonic”)
  • @ScottHunter 我并不是要暗示有什么不是“Pythonic”或高效的——只是好奇是否有更好的方法。

标签: python function lambda closures


【解决方案1】:

这被称为闭包,它是一种非常合理的编写方式,也是最有效的方法之一(无论如何在 CPython 参考解释器中)。

我知道的唯一其他常见模式是相当于 C++ 的仿函数,其中一个类将状态作为属性,附加参数传递给__call__,例如匹配您的情况:

class Line:
    def __init__(self, m, b):
        self.m = m
        self.b = b
    def __call__(self, x):
        return self.m * x + self.b

它的使用方式相同,要么创建/存储实例并重用它,要么如您的示例中那样,创建它,使用它一次,然后将其丢弃 (Line(m, b)(x))。函子虽然比闭包慢(因为属性访问比从嵌套范围读取更昂贵,至少在 CPython 参考解释器中),而且如您所见,它们也更冗长,所以我通常推荐闭包除非您的需求需要类实例更大的灵活性/功能。

【讨论】:

  • partial of some line(m, b, x) 也是另一种选择
  • 也与@ShadowRanger的回答有关,OP可能会觉得object closure duality很有趣
  • @modesitt:我想类似,虽然它的用法不同;必须存在采用所有三个参数的 line 函数,并且包装将直接使用 partial 或使用另一个实用程序函数完成。
【解决方案2】:

我支持@ShaddowRanger 的回答。但是使用partial 是另一种不错的方法。

import functools
def f(m, b, x):
    return m * x + b
line = functools.partial(f, 2, 3)
line(5)
=> 13

值得指出的一点是 lambda 对象和 OP 的 inner_function 不可腌制,而这里的 line 以及 @ShaddowRanger 的 Line 对象是腌制的,这使它们更多有用。

【讨论】:

    【解决方案3】:

    这有点短:

    def line(m,b):
        return lambda x: m*x+b;
    

    【讨论】:

    • 如果我们要走这条路,lambda m, b: lambda x: m*x+b ;)
    • 请注意,在实际代码中,您最好用文档字符串注释内部和外部函数; lambdas 提供了不错的单行代码,但对于文档而言却没有那么多。
    • @modesitt:区别在于inner_functiononly使用在line内部,line可能不是这种情况。
    猜你喜欢
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-19
    • 2020-03-16
    相关资源
    最近更新 更多