__radd__ 操作与 numpy 数字导致 __getitem__ 循环

huangapple go评论69阅读模式
英文:

__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.

huangapple
  • 本文由 发表于 2023年5月7日 02:39:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190531.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定