我们如何在Python中使用sin,cos,tan一般(包括用户定义的类型)?

sel*_*tze 9 python user-defined-types

编辑:让我尝试改写并改进我的问题.旧版本附在底部.

我正在寻找的是一种以类型通用的方式表达和使用自由函数的方法.例子:

abs(x)  # maps to x.__abs__()
next(x) # maps to x.__next__() at least in Python 3
-x      # maps to x.__neg__()
Run Code Online (Sandbox Code Playgroud)

在这些情况下,函数的设计方式允许具有用户定义类型的用户通过将工作委托给非静态方法调用来自定义其行为.这很好.它允许我们编写并不真正关心确切参数类型的函数,只要它们"感觉"像对某个概念建模的对象.

反例:一般不能轻易使用的功能:

math.exp  # only for reals
cmath.exp # takes complex numbers
Run Code Online (Sandbox Code Playgroud)

假设,我想编写一个泛型函数,将exp应用于类似数字的对象列表.我应该使用什么exp函数?如何选择正确的?

def listexp(lst):
    return [math.exp(x) for x in lst]
Run Code Online (Sandbox Code Playgroud)

显然,即使存在复数的exp(在cmath中),这也不适用于复数列表.它也不适用于任何用户定义的类似数字的类型,它可能提供自己的特殊exp函数.

所以,我正在寻找的是一种双方处理这种方式的方法 - 理想情况下,没有特殊的外壳很多东西.作为一些通用函数的编写者,它不关心参数的确切类型,我想使用特定于所涉及类型的正确数学函数,而不必明确地处理它.作为用户定义类型的编写者,我想公开已经扩充的特殊数学函数来处理存储在这些对象中的其他数据(类似于复数的虚部).

这样做的首选模式/协议/习惯用法是什么?我还没考试numpy.但我下载了它的源代码.据我所知,它为数组提供了sin函数.不幸的是,我还没有在源代码中找到它的实现.但是看看他们如何设法为阵列当前存储的正确类型的数字选择正确的sin函数将会很有趣.

在C++中,我会依赖于函数重载和ADL(依赖于参数的查找).在C++被静态类型化的情况下,在编译时完全处理这个(名称查找,重载解析)并不奇怪.我想,我可以在运行时使用Python和Python提供的反射工具来模拟它.但我也知道,尝试将编码风格导入另一种语言可能是一个坏主意,在新语言中并不是非常惯用.所以,如果你对方法有不同的想法,我会全力以赴.

我想,在某些地方,我需要以可扩展的方式手动执行一些类型相关的调度.也许写一个模块"tgmath"(类型泛型数学),它支持真实和复杂的支持,并允许其他人注册他们的类型和特殊情况函数......意见?Python大师对此有何评论?

TIA

编辑:显然,我不是唯一一个对泛型函数和类型相关的重载感兴趣的人.有PEP 3124但它自4年前就处于草案状态.


旧版本的问题:

我有很强的Java和C++背景,最近刚开始学习Python.我想知道的是:我们如何扩展数学函数(至少它们的名称),以便它们可以用于其他用户定义的类型?这些类型的函数是否提供了我可以利用的任何类型的扩展点/钩子(类似于next(obj)实际委托的迭代器协议obj.__next__等)?

在C++中,我会简单地用新参数类型重载函数,并让编译器使用参数表达式的静态类型来确定哪些函数意味着什么.但由于Python是一种非常动态的语言,因此不存在重载.这样做的首选Python方式是什么?

另外,当我编写自定义函数时,我想避免使用长链

if isinstance(arg,someClass):
    suchandsuch
elif ...
Run Code Online (Sandbox Code Playgroud)

我可以使用哪些模式使代码看起来更漂亮,更多Python?

我想,我基本上是在尝试处理Python中缺少函数重载的问题.至少在C++中,重载和依赖于参数的查找是良好C++风格的重要组成部分.

是否有可能

x = udt(something)  # object of user-defined type that represents a number
y = sin(x)          # how do I make this invoke custom type-specific code for sin?
t = abs(x)          # works because abs delegates to __abs__() which I defined.
Run Code Online (Sandbox Code Playgroud)

工作?我知道我可以使罪成为班级的非静态方法.但是后来我失去了通用性,因为对于其他类似数字的对象,它是sin(x)和不是x.sin().

添加__float__方法是不可接受的,因为我在对象中保留了附加信息,例如"自动区分"的衍生物.

TIA

编辑:如果您想了解的代码是什么样子,检查出.在理想的世界中,我将能够以类型通用的方式使用sin/cos/sqrt.我认为这些函数是对象接口的一部分,即使它们是"自由函数".在__somefunction我没有资格的功能math.,也没有__main__..它只是工作,因为我手动math.sin通过装饰器回到我的自定义函数(等).但我认为这是一个丑陋的黑客.

and*_*oke 5

你可以这样做,但它会倒退。__float__()您在新类型中实现,然后sin()将与您的班级一起工作。

换句话说,您不能将 sine 调整为适用于其他类型;您可以调整这些类型,以便它们可以与正弦一起使用。

这更好,因为它强制一致性。如果没有从对象到浮点数的明显映射,那么sin()对该类型可能没有合理的解释。

[抱歉,如果我之前错过了“__float__ 不起作用”部分;也许您是为了回应这一点而添加的?无论如何,为了令人信服地证明你想要的东西是不可能的,python 有 cmath 库来sin()为复数添加等...]

  • 不幸的是,这在我的情况下是不可接受的,因为我尝试使用此自定义类型来自动跟踪导数(自动微分)。 (2认同)

std*_*err 0

通常,此类问题的答案是“你不”或“使用鸭子打字”。您能提供更多关于您想要做什么的细节吗?您是否看过数字类型的其余协议方法?

http://docs.python.org/reference/datamodel.html#emulated-numeric-types