在python中进行多次调度的简单方法? (没有外部库或类构建?)

Posted

技术标签:

【中文标题】在python中进行多次调度的简单方法? (没有外部库或类构建?)【英文标题】:Simple way to do multiple dispatch in python? (No external libraries or class building?) 【发布时间】:2020-05-02 19:37:37 【问题描述】:

我正在编写一个一次性脚本来计算一些我正在运行的模拟的分析解决方案。

我想以某种方式实现一个函数,该函数将根据其输入计算正确答案。例如,假设我有以下数学方程式:

tmax = (s1 - s2) / 2 = q * (a^2 / (a^2 - b^2))

对我来说,我应该能够做这样的事情似乎很简单:

def tmax(s1, s2):
    return (s1 - s2) / 2

def tmax(a, b, q):
    return q * (a**2 / (a**2 - b**2))

我可能已经习惯用julia 写作,但我真的不想让这个脚本变得过于复杂。

【问题讨论】:

我真的不知道你在问什么。您不能定义 2 个具有相同名称的函数。 @Julien 问题是询问multiple dispatch 的具体情况,其中只有参数的数量会影响要调用的实现,而不影响运行时类型。 @Julien 就像凤阳说的,这叫多分派,在python中是可以的,但是目前我读到的所有东西都需要外部包或者构建一个自定义类。我有一个次要但具体的用例。所以我想知道是否有语言固有的特性可以让我做到这一点。 【参考方案1】:

在 C++ 等静态类型语言中,您可以根据输入参数类型(和数量)重载函数,但这在 Python 中是不可能的。任何给定名称只能有一个函数。

可以做的是使用默认参数功能选择两个路径之一该函数中,类似于:

def tmax(p1, p2, p3 = None):
    # Two-argument variant has p3 as None.

    if p3 is None:
        return (p1 - p2) / 2

    # Otherwise, we have three arguments.

    return (p1 * p1 / (p1 * p1 - p2 * p2)) * p3

如果您想知道为什么我将平方运算从 n ** 2 更改为 n * n,那是因为后者更快(或者在过去的某个时间 曾经,,至少对于像2 这样的小型积分幂 - 可能仍然是这种情况,但您可能需要确认)。

一个可能的情况是g1 ** 2 可能比g1 * g1 更快的情况是g1 是全局而不是本地(Python VM 需要更长的时间才能@ 987654328@ 而不是 LOAD_FAST)。发布的代码并非如此,因为该参数本质上是非全局的。

【讨论】:

n ** 2 可能更快的一个原因是它只需要加载一次n,而不是两次。这对于局部变量(快速加载)基本上无关紧要,但对于全局变量(加载成本高)可能很重要。 好点,@Fengyang,在这种特殊情况下并不重要,因为参数是通过LOAD_FAST 而不是LOAD_GLOBAL 获取的。将更新答案以澄清。【参考方案2】:

您可以使用可选参数来做到这一点:

def tmax_2(s1, s2):
    return (s1 - s2) / 2

def tmax_3(a, b, q):
    return q * (a**2 / (a**2 - b**2))

def tmax(a, b, c=None):
    if c is None:
        return tmax_2(a, b)
    else:
        return tmax_3(a, b, c)

【讨论】:

以上是关于在python中进行多次调度的简单方法? (没有外部库或类构建?)的主要内容,如果未能解决你的问题,请参考以下文章

使用泛型进行多次调度

多方法和多调度之间有啥区别吗?

为许多类似功能实现多次调度的有效方法

有没有更简单的方法来进行布尔转换?

在 Flux/React 中调度级联/依赖异步请求

是否可以在 NOT-a-type 上进行多次调度?