gpt4 book ai didi

python - 参数类型在正常和反射运算符重载 (__sub__/__rsub__) 方面不同

转载 作者:行者123 更新时间:2023-11-28 18:49:23 25 4
gpt4 key购买 nike

在通过像 __rsub__ 这样的右手运算符传递 numpy 数组后,如何访问它的属性?

我用 python 写了一个非常简单的类,它定义了两个函数:

class test(object):
def __sub__(self, other):
return other

def __rsub__(self, other):
return other

基本上他们应该做同样的事情。左侧运算符 __sub__ 按预期工作,但 numpy 数组似乎在右侧运算符上剥离了其属性

from skimage import data
from skimage.color import rgb2gray
lena = data.lena()

grayLena = rgb2gray(lena)
t = test()

## overloaded - operator
left_hand = t - grayLena
print left_hand
# Output:
#array([[ 0.60802863, 0.60802863, 0.60779059, ..., 0.64137412,
# 0.57998235, 0.46985725],
# [ 0.60802863, 0.60802863, 0.60779059, ..., 0.64137412,
# 0.57998235, 0.46985725],
# [ 0.60802863, 0.60802863, 0.60779059, ..., 0.64137412,
# 0.57998235, 0.46985725],
# ...,
# [ 0.13746353, 0.13746353, 0.16881412, ..., 0.37271804,
# 0.35559529, 0.34377725],
# [ 0.14617059, 0.14617059, 0.18730588, ..., 0.36788784,
# 0.37292549, 0.38467529],
# [ 0.14617059, 0.14617059, 0.18730588, ..., 0.36788784,
# 0.37292549, 0.38467529]])

right_hand = grayLena - t
print right_hand
# Output:
# array([[0.6080286274509803, 0.6080286274509803, 0.6077905882352941, ...,
# 0.6413741176470589, 0.5799823529411765, 0.4698572549019608],
# [0.6080286274509803, 0.6080286274509803, 0.6077905882352941, ...,
# 0.6413741176470589, 0.5799823529411765, 0.4698572549019608],
# [0.6080286274509803, 0.6080286274509803, 0.6077905882352941, ...,
# 0.6413741176470589, 0.5799823529411765, 0.4698572549019608],
# ...,
# [0.1374635294117647, 0.1374635294117647, 0.1688141176470588, ...,
# 0.3727180392156863, 0.35559529411764706, 0.34377725490196076],
# [0.1461705882352941, 0.1461705882352941, 0.18730588235294118, ...,
# 0.3678878431372549, 0.37292549019607846, 0.3846752941176471],
# [0.1461705882352941, 0.1461705882352941, 0.18730588235294118, ...,
# 0.3678878431372549, 0.37292549019607846, 0.3846752941176471]], dtype=object)

所以这两种操作的区别在于__rsub__接收的是一个dtype=object的数组。如果我只设置这个数组的数据类型,一切都会正常进行。

但是,它仅适用于 __rsub__ 之外的返回值。在我的 __rsub__ 中,我得到的只是垃圾,我无法转换回来,也就是说,如果我这样做了

npArray = np.array(other,  dtype=type(other))

我得到一个类型的一维数组(在我的例子中是 float )。但是由于某种原因,形状信息丢失了。有没有人这样做过或知道如何访问数组的原始属性(形状和类型)?

最佳答案

我不确定 ndarray 机制中的确切控制流是什么,但您的情况或多或少是清楚的:

ndarray 委托(delegate)给对象的 __rsub__ 方法的不是整体减法操作,而是从数组中的每个项目中减去对象。显然,当它必须将操作委托(delegate)给对象的方法时,无论返回什么,返回类型都设置为 object。您可以通过对代码稍作修改来检查它:

class test(object):
def __sub__(self, other):
return other

def __rsub__(self, other):
return other if other != 1 else 666

In [11]: t = test()

In [12]: t - np.arange(4)
Out[12]: array([0, 1, 2, 3])

In [13]: np.arange(4) - t
Out[13]: array([0, 666, 2, 3], dtype=object)

我不认为有一种简单的方法可以覆盖这种行为。你可以试试 making test a subclass of ndarray具有高 __array_priority__ 并滥用一点 __array_wrap__ 方法:

class test(np.ndarray):
__array_priority__ = 100

def __new__(cls):
obj = np.int32([1]).view(cls)
return obj

def __array_wrap__(self, arr, context) :
if context is not None :
ufunc = context[0]
args = context[1]
if ufunc == np.subtract :
if self is args[0] :
return args[1]
elif self is args[1] :
return args[0]
return arr

现在:

>>> t = test()
>>> np.arange(4) - t
array([0, 1, 2, 3])
>>> t - np.arange(4)
array([0, 1, 2, 3])

但是:

>>> np.arange(4) + t
test([1, 2, 3, 4])
>>> t + np.arange(4)
test([1, 2, 3, 4])

有点浪费,因为我们是在做把t里面的1加到数组中的每一个值,然后默默丢弃的操作,但是我想不出任何方法来覆盖它。

关于python - 参数类型在正常和反射运算符重载 (__sub__/__rsub__) 方面不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15340650/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com