英文:
__radd__ operation with numpy number results to __getitem__ loop
问题
I am implementing a class that handles basic binary operations such as addition, multiplication, subraction and division with their respective variants (reversed, in-place). I encountered an unexpected behaviour that I am trying to understand. Unfortunately, even by looking at numpy's implementation of __add__ of unsignedinteger, I can not.
To reproduce this behavior you can simply run this code :
import numpy as np
class test:
def __init__(self):
self.a = 1
def __len__(self):
return 1
def __getitem__(self, index):
print("getitem")
return self.a
def __radd__(self, other):
return self.a + other
a = test()
b = np.uint8(1) + a
It will result in a __getitem__ loop.
Of course my actual code works a bit differently but still faces the exact same issue.
I also tried to use python debugger in order to better understand the behavior of the operation that actually was called.
What I wish to do is mainly, when I run this code :
b = np.uint8(10) + test()
To actually execute __radd__ operation. I understand it is happening because numpy.unsignedinteger.__add__ is executed. Is there any pythonic way to prevent or even better, to fix it?
英文:
I am implementing a class that handles basic binary operations such as addition, multiplication, subraction and division with their respective variants (reversed, in-place). I encountered an unexpected behaviour that I am trying to understand. Unfortunately, even by looking at numpy's implementation of __add__ of unsignedinteger, I can not.
To reproduce this behavior you can simply run this code :
import numpy as np
class test:
def __init__(self):
self.a = 1
def __len__(self):
return 1
def __getitem__(self, index):
print("getitem")
return self.a
def __radd__(self, other):
return self.a + other
a = test()
b = np.uint8(1) + a
It will result in a __getitem__ loop.
Of course my actual code works a bit differently but still faces the exact same issue.
I also tried to use python debugger in order to better understand the behavior of the operation that actually was called.
What I wish to do is mainly, when I run this code :
b = np.uint8(10) + test()
To actually execute __radd__ operation. I understand it is happening because numpy.unsignedinteger.__add__ is execute. Is there any pythonic way to prevent or even better, to fix it ?
答案1
得分: 4
I understand it is happening because numpy.unsignedinteger.__add__ is executed. Is there any pythonic way to prevent or even better, to fix it?
给定表达式 np.uint8(10) + test(),没有办法阻止您的 test 类调用numpy的 __add__ 方法。
只有当numpy在其方法中返回 NotImplemented 时,才会调用您的 __radd__。
您所看到的无限 __getitem__ 循环发生,因为您的类表现得像一个无限序列,numpy想要将其标量添加到该无限序列的每个元素上。这永远不会结束。
您有两种修复方法。第一种选择:将您的类制作成一个合适的有限序列,让numpy处理该操作。这将不会调用您的 __radd__ 方法。
要使您的类成为有限序列,必须在您的 __getitem__ 中当索引大于零或小于负一(-1)时 raise IndexError。
第二种选择:去掉您的 __getitem__ 方法。然后numpy会意识到它不能将自己添加到您的类型中,返回 NotImplemented 并让您的 __radd__ 方法处理该操作。
英文:
> I understand it is happening because numpy.unsignedinteger.__add__ is execute. Is there any pythonic way to prevent or even better, to fix it ?
Given the expression np.uint8(10) + test() there is no way your test class can prevent the calling of numpy's __add__ method.
Only if numpy returned NotImplemented in their method your __radd__ would be called.
The infinite __getitem__ loop you are seeing is happening, because your class behaves like an infinite sequence and numpy wants to add their scalar to every element of that infinite sequence. That will never finish.
You have two ways to fix this. First option: make your class a proper finite sequence and let numpy handle the operation. This will not call your __radd__ method.
To make your class a finite sequence you must raise IndexError in your __getitem__ when the index is larger than zero or less than negative one (-1).
The second option: get rid of your __getitem__ method. Then numpy realizes it cannot add itself to your type, return NotImplemented and let your __radd__ method handle the operation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论