我在包含numpy數組的屬性的類中重載運算符時遇到了一個問題。根據操作數的順序,結果類型將是我的類A(所需行爲)或一個numpy數組。如何使它總是返回一個A的實例?如何使__add__的numpy重載獨立於操作數順序?
例子:
import numpy as np
class A(object):
""" class overloading a numpy array for addition
"""
def __init__(self, values):
self.values = values
def __add__(self, x):
""" addition
"""
x = np.array(x) # make sure input is numpy compatible
return A(self.values + x)
def __radd__(self, x):
""" reversed-order (LHS <-> RHS) addition
"""
x = np.array(x) # make sure input is numpy compatible
return A(x + self.values)
def __array__(self):
""" so that numpy's array() returns values
"""
return self.values
def __repr__(self):
return "A object: "+repr(self.values)
A的一個實例:
>>> a = A(np.arange(5))
這按預期工作:
>>> a + np.ones(5)
A object: array([ 1., 2., 3., 4., 5.])
這不:
>>> np.ones(5) + a
array([ 1., 2., 3., 4., 5.])
即使這是罰款:
>>> list(np.ones(5)) + a
A object: array([ 1., 2., 3., 4., 5.])
什麼發生在第二個例子是RADD不叫可言的,而不是從np.ones(5)numpy的方法__add__
被調用。
我試圖從this post但__array_priority__
幾點建議似乎沒有什麼差別(seberg評論後編輯:至少在numpy的1.7.1,但可以在新版本的工作),並__set_numeric_ops__
導致段錯誤..我想我做錯了什麼。
對上述簡單示例有效的任何建議(同時保留__array__
屬性)?
編輯:我不想讓A成爲np.ndarray的子類,因爲這會伴隨其他併發症,我想避免 - 至少現在。請注意,熊貓似乎已經解決了這個問題:
import pandas as pd
df = pd.DataFrame(np.arange(5))
type(df.values + df) is pd.DataFrame # returns True
isinstance(df, np.ndarray) # returns False
我很想知道這是如何完成的。
解決方案:除了子類的M4rtini解決方案,還可以將__array_wrap__
屬性添加到類A(以避免子類化)。更多here。根據seberg,__array_priority__
也可以在較新的numpy版本上工作(請參閱評論)。
如果添加'__array__',則添加'__array_priority__',不確定是否涵蓋舊版本的所有內容。 – seberg
有沒有特殊的方法來做到這一點?如果我只是添加一個類屬性'__array_priority__ = 1000',它不能解決問題。我也嘗試了0,-1 ...我的numpy版本是1.7.1,這是相當新的,不是嗎? –
你還不是很遠,'__array_wrap__'做了訣竅(見下面的答案) –