简体   繁体   English

如何使math和numpy模块中的现有函数支持用户定义的对象?

[英]How do I make existing functions in math and numpy module support user-defined objects?

I defined a class that I'd like basic operations such as + , - , and even more advanced math operations such as sin to support. 我定义了一个我想要基本操作(例如+- )以及更高级的数学操作(例如sin来支持的类。 That is, I need to define some new rules for these basic operators and math functions. 也就是说,我需要为这些基本运算符和数学函数定义一些新规则。

I could deal with basic operators using Python's magic methods as below, 我可以使用以下Python的魔术方法处理基本运算符,

class NewObj():

    def __init__(self, *args):
        pass

    def __add__(self, other):
        pass

    def __mul__(self, other):
        pass

    # Use magic methods to define other basic operators below...

And I could also redefine basic functions in the same .py file where class NewObj is defined, such as 而且我还可以在定义类NewObj的同一.py文件中重新定义基本功能,例如

def sin(x):
    pass

And name this file as, say, myoperator.py. 并将该文件命名为myoperator.py。 Then I could import this module and apply new operations on NewObj objects. 然后,我可以导入此模块,并对NewObj对象应用新操作。


But I also want existing functions in numpy and math to support my NewObj objects so that math.sin() and numpy.sin() also support my newly defined NewObj objects. 但是我还希望numpymath现有函数支持我的NewObj对象,以便math.sin()numpy.sin()也支持我新定义的NewObj对象。 How can I achieve this? 我该如何实现?

Another question is: is it possible to encapsulate functions inside my NewObj class just like magic methods so that all the stuff are written inside a class data structure? 另一个问题是:是否有可能像魔术方法一样将函数封装在NewObj类中,以便所有内容都写入类数据结构中?

The math module explicitly documents that functions like math.sin always return floats. math模块显式地记录诸如math.sin类的math.sin始终返回浮点数。 If you want math.sin(your_object) to return a NewObj instance instead of a float , don't do that . 如果要让math.sin(your_object)返回一个NewObj实例而不是float请不要这样做 It'll confuse the hell out of everyone if you even make it work, and it'll cause initialization order bugs and other headaches. 如果您使它工作,它将使所有人感到困惑,并且将导致初始化顺序错误和其他麻烦。 (There's a reason NumPy has its own numpy.sin instead of trying to make math.sin support NumPy arrays.) (这是NumPy有其自己的numpy.sin而不是试图使math.sin支持NumPy数组的原因。)

If you're okay with math.sin(your_object) returning a float, then implement a __float__ method to convert your objects to floats: 如果您对math.sin(your_object)返回浮点数没问题,那么可以实现__float__方法将您的对象转换为浮点数:

class NewObj(object):
    ...
    def __float__(self):
        return whatever

math.sin will convert your object to a float, compute the sine of the float, and return the sine as a float. math.sin会将您的对象转换为浮点数,计算该浮点数的正弦值,然后将其作为浮点数返回。


For NumPy, just implement a sin method: 对于NumPy,只需实现一个sin方法:

class NewObj(object):
    ...
    def sin(self):
        return whatever

numpy.sin will delegate to your sin method. numpy.sin将委托给您的sin方法。 You can have it return a NewObj ; 您可以让它返回一个NewObj there's no need to cast to float or anything. 无需强制浮动或其他任何操作。 Most similar NumPy functions will delegate to methods similarly. 大多数类似的NumPy函数将类似地委托给方法。 That said, trying to use custom objects inside NumPy arrays defeats most of the efficiency benefits of NumPy, so you might want to rethink your design if you want to do that. 也就是说,尝试在NumPy数组中使用自定义对象会削弱NumPy的大多数效率优势,因此,如果要这样做,您可能需要重新考虑设计。

You can redefine the math module's sin . 您可以重新定义math模块的sin

import math

class NewObj:
    pass

old_sin = math.sin

def new_sin(number):
    return 42.0 if isinstance(number, NewObj) else old_sin(number)

math.sin = new_sin

Presumably you replace 42.0 with an even more useful definition. 大概您用一个更有用的定义替换了42.0

There will in the hopefully not so far future be a __numpy_ufunc__ special attribute (name subject to change ). 希望在不久的将来不会出现__numpy_ufunc__特殊属性(名称可能会更改 )。 Here's the relevant bit from the numpy docs' dev version 这是numpy docs 开发版本中的相关内容

class.__numpy_ufunc__(ufunc, method, i, inputs, **kwargs)

New in version 1.11. 1.11版中的新功能。

Any class ( ndarray subclass or not ) can define this method to override behavior of NumPy's ufuncs. 任何类( 无论是否为ndarray子类 )都可以定义此方法来覆盖NumPy的ufunc的行为。

[emphasis mine] [强调我的]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM