Last active
January 30, 2016 01:24
-
-
Save lkilcher/d1e2193cbc366adb49c8 to your computer and use it in GitHub Desktop.
Bugs related to NumPy's new __numpy_ufunc__ hook.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
class buggy(object): | |
def __init__(self, arr): | |
self.arr = arr | |
def __pow__(self, other): | |
print "In __pow__" | |
return self.arr ** other | |
def __rpow__(self, other): | |
print "In __rpow__" | |
return other ** self.arr | |
def __ipow__(self, other): | |
print "In __ipow__" | |
self.arr **= other | |
return self | |
def __add__(self, other): | |
print "In __add__" | |
return self.arr + other | |
def __radd__(self, other): | |
print "In __radd__" | |
return other + self.arr | |
def __iadd__(self, other): | |
print "In __iadd__" | |
self.arr += other | |
return self | |
def __numpy_ufunc__(self, ufunc, method, i, inputs, **kwargs): | |
print "In __numpy_ufunc__" | |
a = np.arange(1, 6) | |
g = buggy(np.arange(2, 7)) | |
print 'DOING __iadd__' | |
g += a | |
print g.arr | |
a = np.arange(1, 6) | |
g = buggy(np.arange(2, 7)) | |
print 'DOING reversed __iadd__' | |
a += g | |
print a | |
a = np.arange(1, 6) | |
g = buggy(np.arange(2, 7)) | |
print 'DOING __ipow__' | |
g **= a | |
print g.arr | |
a = np.arange(1, 6) | |
g = buggy(np.arange(2, 7)) | |
print 'DOING reversed __ipow__' | |
a **= g |
I believe this is an unrelated sidenote and probably expected behavior. However, because it throws a similar error I'm pointing it out here.
I noticed that when the __numpy_ufunc__
is not present in the buggy
class, line 48 (a += g
) fails with:
Traceback (most recent call last):
File "test.py", line 48, in <module>
a += g
TypeError: ufunc 'add' output (typecode 'O') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''
I suppose this is expected behavior because __numpy_ufunc__
indicates to NumPy that it should be able to handle this type of object. That is, when __numpy_ufunc__
is not present it throws this error.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code generates the following output and error:
What's strange is that the presence of
__numpy_ufunc__
lets NumPy know that it can redirect thea += g
line to theg.__radd__
method, but the same is not true for thea **= g
line. Why isn'tg.__rpow__
called here?I get this behavior on OSX 10.10.5, with Python 2.7 and NumPy 1.10.4. I also get this error with bleeding-edge NumPy (0bba66).