1

i defined a custom iterator, how can i do multiplication with numpy array and it?

from collections.abc import Iterable

class Vector3d(object):
    def __init__(self, *args):
        if len(args)==3:
            self.x = args[0]
            self.y = args[1]
            self.z = args[2]
        else:
            self.x, self.y, self.z = args[0]
    def _apply(self, func, o):
        if isinstance(o, Iterable):
            xyz = [self.x, self.y, self.z]
            for i,j in enumerate(o):
                xyz[i] = func(xyz[i], j)
            return Vector3d(xyz)
        else:
            return Vector3d(func(self.x, o), func(self.y, o), func(self.z, o))
    def __getitem__(self, i):
        if i=='x' or i==0: return self.x
        if i=='y' or i==1: return self.y
        if i=='z' or i==2: return self.z
    def __repr__(self): return "Vector3d({}, {}, {})".format(self.x, self.y, self.z)
    def __iter__(self): return iter([self.x,self.y,self.z])
    def __neg__(self): return Vector3d(-self.x, -self.y, -self.z)
    def __add__(self, o): return self._apply(lambda x,y: x+y, o)
    def __sub__(self, o): return self._apply(lambda x,y: x-y, o)
    def __mul__(self, o): return self._apply(lambda x,y: x*y, o)
    def __truediv__(self, o): return self._apply(lambda x,y: x/y, o)
    def __eq__(self, o): return all(self._apply(lambda x,y: x==y, o))
    def __ne__(self, o): return any(self._apply(lambda x,y: x!=y, o))

here is what happend when i do multiplication with numpy array and it

>>> a = np.array([[1,2,3],[4,5,6],[5,6,7]])
>>> a*Vector3d(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'int' and 'Vector3d'

it seem numpy think it is not a vector, what should i do? thx

1
  • You're trying to invoke the numpy array's __mul__ because that is the first operand. Unfortunately numpy doesn't know how to multiply its arrays with your objects. Try Vector3d(...) * a or implement __rmul__ Commented Dec 27, 2022 at 14:54

1 Answer 1

3

Use __rmul__ to implement custom behavior when object of your class is right (hence r before mul) to * operator, consider following simple example

import numpy as np
class MyNumber:
    def __init__(self, value):
        self.value = value
    def __rmul__(self, other):
        print("MyNumber.__rmul__ triggered")
        return other * self.value
arr = np.array([1,2,3])
dos = MyNumber(2)
arr2 = arr * dos
print(arr2)

gives output

MyNumber.__rmul__ triggered
MyNumber.__rmul__ triggered
MyNumber.__rmul__ triggered
[2 4 6]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.