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

Skip to content

Commit a36dfbb

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 numpygh-5986.
1 parent 660807e commit a36dfbb

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
@@ -2327,11 +2327,11 @@ def test_dot(self):
23272327

23282328
def test_dot_override(self):
23292329
class A(object):
2330-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
2330+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
23312331
return "A"
23322332

23332333
class B(object):
2334-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
2334+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
23352335
return NotImplemented
23362336

23372337
a = A()
@@ -2943,13 +2943,12 @@ def __lt__(self, other):
29432943
return "nope"
29442944

29452945
class SomeClass2(SomeClass, np.ndarray):
2946-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
2946+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
29472947
if ufunc is np.multiply or ufunc is np.bitwise_and:
29482948
return "ufunc"
29492949
else:
2950-
inputs = list(inputs)
2951-
if i < len(inputs):
2952-
inputs[i] = np.asarray(self)
2950+
inputs = [np.asarray(self) if i is self else i
2951+
for i in inputs]
29532952
func = getattr(ufunc, method)
29542953
if ('out' in kw) and (kw['out'] is not None):
29552954
kw['out'] = np.asarray(kw['out'])
@@ -3027,7 +3026,7 @@ def __rsub__(self, other):
30273026
def test_ufunc_override_normalize_signature(self):
30283027
# gh-5674
30293028
class SomeClass(object):
3030-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
3029+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
30313030
return kw
30323031

30333032
a = SomeClass()
@@ -3044,43 +3043,46 @@ def test_numpy_ufunc_index(self):
30443043
# Check that index is set appropriately, also if only an output
30453044
# is passed on (latter is another regression tests for github bug 4753)
30463045
class CheckIndex(object):
3047-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
3048-
return i
3046+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
3047+
for i, a in enumerate(inputs):
3048+
if a is self:
3049+
return i
3050+
return None
30493051

30503052
a = CheckIndex()
30513053
dummy = np.arange(2.)
30523054
# 1 input, 1 output
30533055
assert_equal(np.sin(a), 0)
3054-
assert_equal(np.sin(dummy, a), 1)
3055-
assert_equal(np.sin(dummy, out=a), 1)
3056-
assert_equal(np.sin(dummy, out=(a,)), 1)
3056+
assert_equal(np.sin(dummy, a), None)
3057+
assert_equal(np.sin(dummy, out=a), None)
3058+
assert_equal(np.sin(dummy, out=(a,)), None)
30573059
assert_equal(np.sin(a, a), 0)
30583060
assert_equal(np.sin(a, out=a), 0)
30593061
assert_equal(np.sin(a, out=(a,)), 0)
30603062
# 1 input, 2 outputs
3061-
assert_equal(np.modf(dummy, a), 1)
3062-
assert_equal(np.modf(dummy, None, a), 2)
3063-
assert_equal(np.modf(dummy, dummy, a), 2)
3064-
assert_equal(np.modf(dummy, out=a), 1)
3065-
assert_equal(np.modf(dummy, out=(a,)), 1)
3066-
assert_equal(np.modf(dummy, out=(a, None)), 1)
3067-
assert_equal(np.modf(dummy, out=(a, dummy)), 1)
3068-
assert_equal(np.modf(dummy, out=(None, a)), 2)
3069-
assert_equal(np.modf(dummy, out=(dummy, a)), 2)
3063+
assert_equal(np.modf(dummy, a), None)
3064+
assert_equal(np.modf(dummy, None, a), None)
3065+
assert_equal(np.modf(dummy, dummy, a), None)
3066+
assert_equal(np.modf(dummy, out=a), None)
3067+
assert_equal(np.modf(dummy, out=(a,)), None)
3068+
assert_equal(np.modf(dummy, out=(a, None)), None)
3069+
assert_equal(np.modf(dummy, out=(a, dummy)), None)
3070+
assert_equal(np.modf(dummy, out=(None, a)), None)
3071+
assert_equal(np.modf(dummy, out=(dummy, a)), None)
30703072
assert_equal(np.modf(a, out=(dummy, a)), 0)
30713073
# 2 inputs, 1 output
30723074
assert_equal(np.add(a, dummy), 0)
30733075
assert_equal(np.add(dummy, a), 1)
3074-
assert_equal(np.add(dummy, dummy, a), 2)
3076+
assert_equal(np.add(dummy, dummy, a), None)
30753077
assert_equal(np.add(dummy, a, a), 1)
3076-
assert_equal(np.add(dummy, dummy, out=a), 2)
3077-
assert_equal(np.add(dummy, dummy, out=(a,)), 2)
3078+
assert_equal(np.add(dummy, dummy, out=a), None)
3079+
assert_equal(np.add(dummy, dummy, out=(a,)), None)
30783080
assert_equal(np.add(a, dummy, out=a), 0)
30793081

30803082
def test_out_override(self):
30813083
# regression test for github bug 4753
30823084
class OutClass(np.ndarray):
3083-
def __array_ufunc__(self, ufunc, method, i, inputs, **kw):
3085+
def __array_ufunc__(self, ufunc, method, inputs, **kw):
30843086
if 'out' in kw:
30853087
tmp_kw = kw.copy()
30863088
tmp_kw.pop('out')
@@ -5213,14 +5215,14 @@ class A(np.ndarray):
52135215
def __new__(cls, *args, **kwargs):
52145216
return np.array(*args, **kwargs).view(cls)
52155217

5216-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
5218+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
52175219
return "A"
52185220

52195221
class B(np.ndarray):
52205222
def __new__(cls, *args, **kwargs):
52215223
return np.array(*args, **kwargs).view(cls)
52225224

5223-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
5225+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
52245226
return NotImplemented
52255227

52265228
a = A([1, 2])

numpy/core/tests/test_ufunc.py

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

12271227
class MyA(np.ndarray):
1228-
def __array_ufunc__(self, ufunc, method, i, inputs, **kwargs):
1228+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
12291229
return getattr(ufunc, method)(*(input.view(np.ndarray)
12301230
for input in inputs), **kwargs)
12311231
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
@@ -1543,8 +1543,8 @@ def __array__(self):
15431543
def test_ufunc_override(self):
15441544

15451545
class A(object):
1546-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1547-
return self, func, method, pos, inputs, kwargs
1546+
def __array_ufunc__(self, func, method, inputs, **kwargs):
1547+
return self, func, method, inputs, kwargs
15481548

15491549
a = A()
15501550
b = np.matrix([1])
@@ -1558,12 +1558,10 @@ def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
15581558
assert_equal(res1[1], np.dot)
15591559
assert_equal(res0[2], '__call__')
15601560
assert_equal(res1[2], '__call__')
1561-
assert_equal(res0[3], 0)
1562-
assert_equal(res1[3], 0)
1563-
assert_equal(res0[4], (a, b))
1564-
assert_equal(res1[4], (a, b))
1565-
assert_equal(res0[5], {})
1566-
assert_equal(res1[5], {})
1561+
assert_equal(res0[3], (a, b))
1562+
assert_equal(res1[3], (a, b))
1563+
assert_equal(res0[4], {})
1564+
assert_equal(res1[4], {})
15671565

15681566
def test_ufunc_override_mro(self):
15691567

@@ -1579,23 +1577,23 @@ def quatro_mul(a, b, c, d):
15791577
four_mul_ufunc = np.frompyfunc(quatro_mul, 4, 1)
15801578

15811579
class A(object):
1582-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1580+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15831581
return "A"
15841582

15851583
class ASub(A):
1586-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1584+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15871585
return "ASub"
15881586

15891587
class B(object):
1590-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1588+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15911589
return "B"
15921590

15931591
class C(object):
1594-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1592+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15951593
return NotImplemented
15961594

15971595
class CSub(object):
1598-
def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
1596+
def __array_ufunc__(self, func, method, inputs, **kwargs):
15991597
return NotImplemented
16001598

16011599
a = A()
@@ -1659,27 +1657,25 @@ def __array_ufunc__(self, func, method, pos, inputs, **kwargs):
16591657
def test_ufunc_override_methods(self):
16601658

16611659
class A(object):
1662-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
1663-
return self, ufunc, method, pos, inputs, kwargs
1660+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
1661+
return self, ufunc, method, inputs, kwargs
16641662

16651663
# __call__
16661664
a = A()
16671665
res = np.multiply.__call__(1, a, foo='bar', answer=42)
16681666
assert_equal(res[0], a)
16691667
assert_equal(res[1], np.multiply)
16701668
assert_equal(res[2], '__call__')
1671-
assert_equal(res[3], 1)
1672-
assert_equal(res[4], (1, a))
1673-
assert_equal(res[5], {'foo': 'bar', 'answer': 42})
1669+
assert_equal(res[3], (1, a))
1670+
assert_equal(res[4], {'foo': 'bar', 'answer': 42})
16741671

16751672
# reduce, positional args
16761673
res = np.multiply.reduce(a, 'axis0', 'dtype0', 'out0', 'keep0')
16771674
assert_equal(res[0], a)
16781675
assert_equal(res[1], np.multiply)
16791676
assert_equal(res[2], 'reduce')
1680-
assert_equal(res[3], 0)
1681-
assert_equal(res[4], (a,))
1682-
assert_equal(res[5], {'dtype':'dtype0',
1677+
assert_equal(res[3], (a,))
1678+
assert_equal(res[4], {'dtype':'dtype0',
16831679
'out': 'out0',
16841680
'keepdims': 'keep0',
16851681
'axis': 'axis0'})
@@ -1690,9 +1686,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
16901686
assert_equal(res[0], a)
16911687
assert_equal(res[1], np.multiply)
16921688
assert_equal(res[2], 'reduce')
1693-
assert_equal(res[3], 0)
1694-
assert_equal(res[4], (a,))
1695-
assert_equal(res[5], {'dtype':'dtype0',
1689+
assert_equal(res[3], (a,))
1690+
assert_equal(res[4], {'dtype':'dtype0',
16961691
'out': 'out0',
16971692
'keepdims': 'keep0',
16981693
'axis': 'axis0'})
@@ -1702,9 +1697,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
17021697
assert_equal(res[0], a)
17031698
assert_equal(res[1], np.multiply)
17041699
assert_equal(res[2], 'accumulate')
1705-
assert_equal(res[3], 0)
1706-
assert_equal(res[4], (a,))
1707-
assert_equal(res[5], {'dtype':'dtype0',
1700+
assert_equal(res[3], (a,))
1701+
assert_equal(res[4], {'dtype':'dtype0',
17081702
'out': 'out0',
17091703
'axis': 'axis0'})
17101704

@@ -1714,9 +1708,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
17141708
assert_equal(res[0], a)
17151709
assert_equal(res[1], np.multiply)
17161710
assert_equal(res[2], 'accumulate')
1717-
assert_equal(res[3], 0)
1718-
assert_equal(res[4], (a,))
1719-
assert_equal(res[5], {'dtype':'dtype0',
1711+
assert_equal(res[3], (a,))
1712+
assert_equal(res[4], {'dtype':'dtype0',
17201713
'out': 'out0',
17211714
'axis': 'axis0'})
17221715

@@ -1725,9 +1718,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
17251718
assert_equal(res[0], a)
17261719
assert_equal(res[1], np.multiply)
17271720
assert_equal(res[2], 'reduceat')
1728-
assert_equal(res[3], 0)
1729-
assert_equal(res[4], (a, [4, 2]))
1730-
assert_equal(res[5], {'dtype':'dtype0',
1721+
assert_equal(res[3], (a, [4, 2]))
1722+
assert_equal(res[4], {'dtype':'dtype0',
17311723
'out': 'out0',
17321724
'axis': 'axis0'})
17331725

@@ -1737,9 +1729,8 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
17371729
assert_equal(res[0], a)
17381730
assert_equal(res[1], np.multiply)
17391731
assert_equal(res[2], 'reduceat')
1740-
assert_equal(res[3], 0)
1741-
assert_equal(res[4], (a, [4, 2]))
1742-
assert_equal(res[5], {'dtype':'dtype0',
1732+
assert_equal(res[3], (a, [4, 2]))
1733+
assert_equal(res[4], {'dtype':'dtype0',
17431734
'out': 'out0',
17441735
'axis': 'axis0'})
17451736

@@ -1748,26 +1739,24 @@ def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
17481739
assert_equal(res[0], a)
17491740
assert_equal(res[1], np.multiply)
17501741
assert_equal(res[2], 'outer')
1751-
assert_equal(res[3], 0)
1752-
assert_equal(res[4], (a, 42))
1753-
assert_equal(res[5], {})
1742+
assert_equal(res[3], (a, 42))
1743+
assert_equal(res[4], {})
17541744

17551745
# at
17561746
res = np.multiply.at(a, [4, 2], 'b0')
17571747
assert_equal(res[0], a)
17581748
assert_equal(res[1], np.multiply)
17591749
assert_equal(res[2], 'at')
1760-
assert_equal(res[3], 0)
1761-
assert_equal(res[4], (a, [4, 2], 'b0'))
1750+
assert_equal(res[3], (a, [4, 2], 'b0'))
17621751

17631752
def test_ufunc_override_out(self):
17641753

17651754
class A(object):
1766-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
1755+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
17671756
return kwargs
17681757

17691758
class B(object):
1770-
def __array_ufunc__(self, ufunc, method, pos, inputs, **kwargs):
1759+
def __array_ufunc__(self, ufunc, method, inputs, **kwargs):
17711760
return kwargs
17721761

17731762
a = A()

0 commit comments

Comments
 (0)
0