Question
Why do NumPy scalars multiply with custom sequences but not with lists?
I have a question to NumPy experts. Consider a NumPy scalar: c = np.arange(3.0).sum()
. If I try to multiply it with a custom sequence like e.g.
class S:
def __init__(self, lst):
self.lst = lst
def __len__(self):
return len(self.lst)
def __getitem__(self, s):
return self.lst[s]
c = np.arange(3.0).sum()
s = S([1, 2, 3])
print(c * s)
it works and I get: array([3., 6., 9.])
.
However, I can't do so with a list. For instance, if I inherit S from list and try it, this does not work anymore
class S(list):
def __init__(self, lst):
self.lst = lst
def __len__(self):
return len(self.lst)
def __getitem__(self, s):
return self.lst[s]
c = np.arange(3.0).sum()
s = S([1, 2, 3])
print(c * s)
and I get "can't multiply sequence by non-int of type 'numpy.float64'".
So how does NumPy distinguish between the two cases?
I am asking because I want to prevent such behavior for my "S" class without inheriting from list.
UPD
Since the question has been misunderstood a few times, I try to stress more exactly what the problem is. It's not about why the list does not cope with multiplication by float and the error is raised.
It is about why in the first case (when S is NOT inherited from list) the multiplication is performed by the object "c" and in the second case (when S is inherited from list) the multiplication is delegated to "s".
Apparently, the method c.__mul__
does some checks which pass in the first case, but fail in the second case, so that s.__rmul__
is called. The question is essentially: What are those checks? (I strongly doubt that this is anything like isinstance(other, list)
).