8000 ENH: Remove position arg from __array_ufunc__. · numpy/numpy@07b0e5c · GitHub
[go: up one dir, main page]

Skip to content

Commit 07b0e5c

Browse files
committed
ENH: Remove position arg from __array_ufunc__.
Previously when __array_ufunc__ for one of the ufunc arguments was called, that arguments position was passed in the call. This PR removes that argument as proposed in gh-5986.
1 parent 88845c0 commit 07b0e5c

File tree

5 files changed

+64
-81
lines changed

5 files changed

+64
-81
lines changed

doc/source/reference/arrays.classes.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Special attributes and methods
3939

4040
NumPy provides several hooks that classes can customize:
4141

42-
.. method:: class.__array_ufunc__(ufunc, method, i, inputs, **kwargs)
42+
.. method:: class.__array_ufunc__(ufunc, method, inputs, **kwargs)
4343

4444
.. versionadded:: 1.11
4545

@@ -51,7 +51,6 @@ NumPy provides several hooks that classes can customize:
5151
- *method* is a string indicating which Ufunc method was called
5252
(one of ``"__call__"``, ``"reduce"``, ``"reduceat"``,
5353
``"accumulate"``, ``"outer"``, ``"inner"``).
54-
- *i* is the index of *self* in *inputs*.
5554
- *inputs* is a tuple of the input arguments to the ``ufunc``
5655
- *kwargs* is a dictionary containing the optional input arguments
5756
of the ufunc. The ``out`` argument is always contained in

numpy/core/src/private/ufunc_override.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
177177
int nin)
178178
{
179179
int i;
180-
int override_pos; /* Position of override in args.*/
181180
int j;
182181

183182
int nargs;
@@ -195,9 +194,6 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
195194

196195
PyObject *with_override[NPY_MAXARGS];
197196

198-
/* Pos of each override in args */
199-
int with_override_pos[NPY_MAXARGS];
200-
201197
/*
202198
* Check inputs
203199
*/
@@ -251,7 +247,6 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
251247
}
252248
if (PyObject_HasAttrString(obj, "__array_ufunc__")) {
253249
with_override[noa] = obj;
254-
with_override_pos[noa] = i;
255250
++noa;
256251
}
257252
}
@@ -336,7 +331,6 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
336331
}
337332

338333
/* Get the first instance of an overriding arg.*/
339-
override_pos = with_override_pos[i];
340334
override_obj = obj;
341335

342336
/* Check for sub-types to the right of obj. */
@@ -372,8 +366,7 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
372366
goto fail;
373367
}
374368

375-
override_args = Py_BuildValue("OOiO", ufunc, method_name,
376-
override_pos, normal_args);
369+
override_args = Py_BuildValue("OOO", ufunc, method_name, normal_args);
377370
if (override_args == NULL) {
378371
Py_DECREF(numpy_ufunc);
379372
goto fail;

numpy/core/tests/test_multiarray.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,11 +2282,11 @@ def test_dot(self):
22822282

22832283
def test_dot_override(self):
22842284
class A(object):
2285-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
2285+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
22862286
return "A"
22872287

22882288
class B(object):
2289-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
2289+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
22902290
return NotImplemented
22912291

22922292
a = A()
@@ -2835,13 +2835,12 @@ def __lt__(self, other):
28352835
return "nope"
28362836

28372837
class SomeClass2(SomeClass, np.ndarray):
2838-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
2838+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
28392839
if ufunc is np.multiply or ufunc is np.bitwise_and:
28402840
return "ufunc"
28412841
else:
2842-
inputs = list(inputs)
2843-
if i < len(inputs):
2844-
inputs[i] = np.asarray(self)
2842+
inputs = [np.asarray(self) if i is self else i
2843+
for i in inputs]
28452844
func = getattr(ufunc, method)
28462845
if ('out' in kw) and (kw['out'] is not None):
28472846
kw['out'] = np.asarray(kw['out'])
@@ -2919,7 +2918,7 @@ def __rsub__(self, other):
29192918
def test_ufunc_override_normalize_signature(self):
29202919
# gh-5674
29212920
class SomeClass(object):
2922-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
2921+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
29232922
return kw
29242923

29252924
a = SomeClass()
@@ -2936,43 +2935,46 @@ def test_numpy_ufunc_index(self):
29362935
# Check that index is set appropriately, also if only an output
29372936
# is passed on (latter is another regression tests for github bug 4753)
29382937
class CheckIndex(object):
2939-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
2940-
return i
2938+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
2939+
for i, a in enumerate(inputs):
2940+
if a is self:
2941+
return i
2942+
return None
29412943

29422944
a = CheckIndex()
29432945
dummy = np.arange(2.)
29442946
# 1 input, 1 output
29452947
assert_equal(np.sin(a), 0)
2946-
assert_equal(np.sin(dummy, a), 1)
2947-
assert_equal(np.sin(dummy, out=a), 1)
2948-
assert_equal(np.sin(dummy, out=(a,)), 1)
2948+
assert_equal(np.sin(dummy, a), None)
2949+
assert_equal(np.sin(dummy, out=a), None)
2950+
assert_equal(np.sin(dummy, out=(a,)), None)
29492951
assert_equal(np.sin(a, a), 0)
29502952
assert_equal(np.sin(a, out=a), 0)
29512953
assert_equal(np.sin(a, out=(a,)), 0)
29522954
# 1 input, 2 outputs
2953-
assert_equal(np.modf(dummy, a), 1)
2954-
assert_equal(np.modf(dummy, None, a), 2)
2955-
assert_equal(np.modf(dummy, dummy, a), 2)
2956-
assert_equal(np.modf(dummy, out=a), 1)
2957-
assert_equal(np.modf(dummy, out=(a,)), 1)
2958-
assert_equal(np.modf(dummy, out=(a, None)), 1)
2959-
assert_equal(np.modf(dummy, out=(a, dummy)), 1)
2960-
assert_equal(np.modf(dummy, out=(None, a)), 2)
2961-
assert_equal(np.modf(dummy, out=(dummy, a)), 2)
2955+
assert_equal(np.modf(dummy, a), None)
2956+
assert_equal(np.modf(dummy, None, a), None)
2957+
assert_equal(np.modf(dummy, dummy, a), None)
2958+
assert_equal(np.modf(dummy, out=a), None)
2959+
assert_equal(np.modf(dummy, out=(a,)), None)
2960+
assert_equal(np.modf(dummy, out=(a, None)), None)
2961+
assert_equal(np.modf(dummy, out=(a, dummy)), None)
2962+
assert_equal(np.modf(dummy, out=(None, a)), None)
2963+
assert_equal(np.modf(dummy, out=(dummy, a)), None)
29622964
assert_equal(np.modf(a, out=(dummy, a)), 0)
29632965
# 2 inputs, 1 output
29642966
assert_equal(np.add(a, dummy), 0)
29652967
assert_equal(np.add(dummy, a), 1)
2966-
assert_equal(np.add(dummy, dummy, a), 2)
2968+
assert_equal(np.add(dummy, dummy, a), None)
29672969
assert_equal(np.add(dummy, a, a), 1)
2968-
assert_equal(np.add(dummy, dummy, out=a), 2)
2969-
assert_equal(np.add(dummy, dummy, out=(a,)), 2)
2970+
assert_equal(np.add(dummy, dummy, out=a), None)
2971+
assert_equal(np.add(dummy, dummy, out=(a,)), None)
29702972
assert_equal(np.add(a, dummy, out=a), 0)
29712973

29722974
def test_out_override(self):
29732975
# regression test for github bug 4753
29742976
class OutClass(np.ndarray):
2975-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
2977+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
29762978
if 'out' in kw:
29772979
tmp_kw = kw.copy()
29782980
tmp_kw.pop('out')
@@ -5090,14 +5092,14 @@ class A(np.ndarray):
50905092
def __new__(cls, *args, **kwargs):
50915093
return np.array(*args, **kwargs).view(cls)
50925094

5093-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
5095+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
50945096
return "A"
50955097

50965098
class B(np.ndarray):
50975099
def __new__(cls, *args, **kwargs):
50985100
return np.array(*args, **kwargs).view(cls)
50995101

5100-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
5102+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
51015103
return NotImplemented
51025104

51035105
a = A([1, 2])

numpy/core/tests/test_ufunc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1226,7 +1226,7 @@ def test_structured_equal(self):
12261226
# https://github.com/numpy/numpy/issues/4855
12271227

12281228
class MyA(np.ndarray):
1229-
def __array_ufunc__(self, ufunc, method, i, inputs, **kwargs):
1229+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
12301230
return getattr(ufunc, method)(*(input.view(np.ndarray)
12311231
for input in inputs), **kwargs)
12321232
a = np.arange(12.).reshape(4,3)

numpy/core/tests/test_umath.py

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,8 +1451,8 @@ def __array__(self):
14511451
def test_ufunc_override(self):
14521452

14531453
class A(object):
1454-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1455-
return self, func, method, pos, inputs, kwargs
1454+
def __array_ufunc__(self, func, method, inputs, **kwargs):
1455+
return self, func, method, inputs, kwargs
14561456

14571457
a = A()
14581458
b = np.matrix([1])
@@ -1466,12 +1466,10 @@ def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
14661466
assert_equal(res1[1], np.dot)
14671467
assert_equal(res0[2], '__call__')
14681468
assert_equal(res1[2], '__call__')
1469-
assert_equal(res0[3], 0)
1470-
assert_equal(res1[3], 0)
1471-
assert_equal(res0[4], (a, b))
1472-
assert_equal(res1[4], (a, b))
1473-
assert_equal(res0[5], {})
1474-
assert_equal(res1[5], {})
1469+
assert_equal(res0[3], (a, b))
1470+
assert_equal(res1[3], (a, b))
1471+
assert_equal(res0[4], {})
1472+
assert_equal(res1[4], {})
14751473

14761474
def test_ufunc_override_mro(self):
14771475

@@ -1487,23 +1485,23 @@ def quatro_mul(a, b, c, d):
14871485
four_mul_ufunc = np.frompyfunc(quatro_mul, 4, 1)
14881486

14891487
class A(object):
1490-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1488+
def __array_ufunc__(self, func, method, inputs, **kwargs):
14911489
return "A"
14921490

14931491
class ASub(A):
1494-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1492+
def __array_ufunc__(self, func, method, inputs, **kwargs):
14951493
return "ASub"
14961494

14971495
class B(object):
1498-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1496+
def __array_ufunc__(self, func, method, inputs, **kwargs):
14991497
return "B"
15001498

15011499
class C(object):
1502-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1500+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15031501
return NotImplemented
15041502

15051503
class CSub(object):
1506-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1504+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15071505
return NotImplemented
15081506

15091507
a = A()
@@ -1567,27 +1565,25 @@ def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
15671565
def test_ufunc_override_methods(self):
15681566

15691567
class A(object):
1570-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
1571-
return self, ufunc, method, pos, inputs, kwargs
1568+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
1569+
return self, ufunc, method, inputs, kwargs
15721570

15731571
# __call__
15741572
a = A()
15751573
res = np.multiply.__call__(1, a, foo='bar', answer=42)
15761574
assert_equal(res[0], a)
15771575
assert_equal(res[1], np.multiply)
15781576
assert_equal(res[2], '__call__')
1579-
assert_equal(res[3], 1)
1580-
assert_equal(res[4], (1, a))
1581-
assert_equal(res[5], {'foo': 'bar', 'answer': 42})
1577+
assert_equal(res[3], (1, a))
1578+
assert_equal(res[4], {'foo': 'bar', 'answer': 42})
15821579

15831580
# reduce, positional args
15841581
res = np.multiply.reduce(a, 'axis0', 'dtype0', 'out0', 'keep0')
15851582
assert_equal(res[0], a)
15861583
assert_equal(res[1], np.multiply)
15871584
assert_equal(res[2], 'reduce')
1588-
assert_equal(res[3], 0)
1589-
assert_equal(res[4], (a,))
1590-
assert_equal(res[5], {'dtype':'dtype0',
1585+
assert_equal(res[3], (a,))
1586+
assert_equal(res[4], {'dtype':'dtype0',
15911587
'out': 'out0',
15921588
'keepdims': 'keep0',
15931589
'axis': 'axis0'})
@@ -1598,9 +1594,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
15981594
assert_equal(res[0], a)
15991595
assert_equal(res[1], np.multiply)
16001596
assert_equal(res[2], 'reduce')
1601-
assert_equal(res[3], 0)
1602-
assert_equal(res[4], (a,))
1603-
assert_equal(res[5], {'dtype':'dtype0',
1597+
assert_equal(res[3], (a,))
1598+
assert_equal(res[4], {'dtype':'dtype0',
16041599
'out': 'out0',
16051600
'keepdims': 'keep0',
16061601
'axis': 'axis0'})
@@ -1610,9 +1605,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
16101605
assert_equal(res[0], a)
16111606
assert_equal(res[1], np.multiply)
16121607
assert_equal(res[2], 'accumulate')
1613-
assert_equal(res[3], 0)
1614-
assert_equal(res[4], (a,))
1615-
assert_equal(res[5], {'dtype':'dtype0',
1608+
assert_equal(res[3], (a,))
1609+
assert_equal(res[4], {'dtype':'dtype0',
16161610
'out': 'out0',
16171611
'axis': 'axis0'})
16181612

@@ -1622,9 +1616,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
16221616
assert_equal(res[0], a)
16231617
assert_equal(res[1], np.multiply)
16241618
assert_equal(res[2], 'accumulate')
1625-
assert_equal(res[3], 0)
1626-
assert_equal(res[4], (a,))
1627-
assert_equal(res[5], {'dtype':'dtype0',
1619+
assert_equal(res[3], (a,))
1620+
assert_equal(res[4], {'dtype':'dtype0',
16281621
'out': 'out0',
16291622
'axis': 'axis0'})
16301623

@@ -1633,9 +1626,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
16331626
assert_equal(res[0], a)
16341627
assert_equal(res[1], np.multiply)
16351628
assert_equal(res[2], 'reduceat')
1636-
assert_equal(res[3], 0)
1637-
assert_equal(res[4], (a, [4, 2]))
1638-
assert_equal(res[5], {'dtype':'dtype0',
1629+
assert_equal(res[3], (a, [4, 2]))
1630+
assert_equal(res[4], {'dtype':'dtype0',
16391631
'out': 'out0',
16401632
'axis': 'axis0'})
16411633

@@ -1645,9 +1637,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
16451637
assert_equal(res[0], a)
16461638
assert_equal(res[1], np.multiply)
16471639
assert_equal(res[2], 'reduceat')
1648-
assert_equal(res[3], 0)
1649-
assert_equal(res[4], (a, [4, 2]))
1650-
assert_equal(res[5], {'dtype':'dtype0',
1640+
assert_equal(res[3], (a, [4, 2]))
1641+
assert_equal(res[4], {'dtype':'dtype0',
16511642
'out': 'out0',
16521643
'axis': 'axis0'})
16531644

@@ -1656,26 +1647,24 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
16561647
assert_equal(res[0], a)
16571648
assert_equal(res[1], np.multiply)
16581649
assert_equal(res[2], 'outer')
1659-
assert_equal(res[3], 0)
1660-
assert_equal(res[4], (a, 42))
1661-
assert_equal(res[5], {})
1650+
assert_equal(res[3], (a, 42))
1651+
assert_equal(res[4], {})
16621652

16631653
# at
16641654
res = np.multiply.at(a, [4, 2], 'b0')
16651655
assert_equal(res[0], a)
16661656
assert_equal(res[1], np.multiply)
16671657
assert_equal(res[2], 'at')
1668-
assert_equal(res[3], 0)
1669-
assert_equal(res[4], (a, [4, 2], 'b0'))
1658+
assert_equal(res[3], (a, [4, 2], 'b0'))
16701659

16711660
def test_ufunc_override_out(self):
16721661

16731662
class A(object):
1674-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
1663+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
16751664
return kwargs
16761665

16771666
class B(object):
1678-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
1667+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
16791668
return kwargs
16801669

16811670
a = A()

0 commit comments

Comments
 (0)
0