2017-02-12 22 views
1

我定義了一個我喜歡基本操作的類,如+,-,甚至更高級的數學運算,如sin來支持。也就是說,我需要爲這些基本的運算符和數學函數定義一些新的規則。如何讓數學和numpy模塊中的現有功能支持用戶定義的對象?

我可以處理使用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... 

而且我也可以重新定義在類NewObj的定義相同.py文件的基本功能,如

def sin(x): 
    pass 

並將該文件命名爲myoperator.py。然後,我可以導入此模塊並在NewObj對象上應用新操作。


但我也想在numpymath現有的功能來支持我的NewObj對象,以便math.sin()numpy.sin()也支持我的新定義NewObj對象。我怎樣才能做到這一點?

另一個問題是:是否有可能將函數封裝在我的NewObj類中,就像魔術方法一樣,以便所有東西都寫在類數據結構中?

回答

3

math模塊明確的文件,像math.sin函數總是返回浮動。如果您想math.sin(your_object)返回NewObj實例而不是float,不要那樣做。如果你使它工作,它會把所有人都搞糊塗,並且會導致初始化錯誤和其他令人頭痛的問題。 (有一個原因NumPy有自己的numpy.sin而不是試圖使math.sin支持NumPy陣列。)

如果您能夠接受math.sin(your_object)返回浮點數,則實現__float__方法,你的對象轉換爲浮動:

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

math.sin將你的對象轉換爲浮動,計算浮動的正弦,並將正弦返回爲浮點數。


對於NumPy的,只是實現sin方法:

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

numpy.sin將委託給你的sin方法。你可以讓它返回NewObj;沒有必要投入浮動或任何東西。大多數類似的NumPy函數將相似地委託給方法。也就是說,試圖在NumPy數組內使用自定義對象會損害NumPy的大部分效率優勢,所以如果您想這樣做,您可能需要重新考慮您的設計。

+0

重新回答你的答案。這看起來非常有用。它與當前的__array_priority__和朋友有什麼關係?未來的'__numpy_ufunc__'就是這個問題?你能提供一個指針嗎?謝謝! –

+0

@PaulPanzer:我不認爲'__array_priority__'會出現在這種情況下。至於'__numpy_ufunc__',我不知道'__numpy_ufunc__'如何與此交互。 – user2357112

2

您可以重新定義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 

想必您用42.0替換爲更有用的定義。

+0

適合我。如果我寫'輸入數學;將myoperator導入爲mo;在腳本中打印(math.sin(mo.NewObj()))'並運行它,它會打印'42.0'。我正在使用CPython 3.6.0。 –

+0

爲了能夠調用math.sin,你仍然必須在腳本中顯式地導入數學,但是,導入myoperator重新定義了'math.sin'的行爲。我不認爲這個不好的原因是'math.sin'的重新定義並沒有改變它對它已經定義的數據類型的作用。它只會添加一個可以應用的新類型,所以更改不應該破壞其他任何代碼。 –

+0

我現在看到了(也適用於我),謝謝! – Nicholas

1

有希望不會成爲未來的__numpy_ufunc__特殊屬性(名稱取決於change)。下面是相關的位由numpy的文檔dev version

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

新的版本1.11。

任何類(ndarray子類或不是)都可以定義此方法以覆蓋NumPy的ufuncs的行爲。

[重點煤礦]

+2

@MadPhysicist「根本不回答問題」?如果你閱讀Q,我想你會發現OP非常具體地要求'數學'和'numpy'功能。所以這個覆蓋了50%。還有神奇的方法標籤。不'ufuncs'的Numpy函數在這裏幾乎沒有關係。此外,爲什麼這種消極的態度? –

+0

如果它涉及到足夠漂亮的格式,我更喜歡在「答案」中看到信息而不是評論。但我不確定這在OP的情況下是有用的。當ndarray子類需要'ufunc'的特殊行爲時,它看起來會更有用。定義'ufunc'可能超出了OP的需求。 – hpaulj

+0

@hpaulj好,它確實說「任何類(ndarray子類或不)」但我承認我並不真正瞭解它是如何融合在一起的。 –

相關問題