diff options
author | Nico Schlömer <nico.schloemer@gmail.com> | 2023-04-20 18:00:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-20 18:00:59 +0200 |
commit | 1acac891f99075128450aacf2a4538de3ff9d028 (patch) | |
tree | d7de52ce7cbac0e2ae51eb68ec2ca4289a9eb77f /numpy/core/src/multiarray | |
parent | 64e692f741da5bf781870de7f6cd1aa5bb5a4070 (diff) | |
download | numpy-1acac891f99075128450aacf2a4538de3ff9d028.tar.gz |
DEP: deprecate scalar conversions for arrays with ndim > 0 (#10615)
This PR reflects some of the progress achieved in issue #10404 and is used to asses the impact of the changes.
With the changes in this PR, `float(numpy.array([1.0])` now gives a warning; likewise some other things:
```python
import numpy
a = numpy.random.rand(10, 1)
a[0] = numpy.array([1.0]) # okay
a[0] = numpy.array(1.0) # okay
a[0] = 1.0 # okay
b = numpy.random.rand(10)
b[0] = numpy.array([1.0]) # ValueError: setting an array element with a sequence.
b[0, ...] = numpy.array([1.0]) # okay
b[0] = numpy.array(1.0) # okay
b[0] = 1.0 # okay
```
This aligns the behavior of numpy arrays with that of lists:
```python
float([3.14])
```
```
TypeError: float() argument must be a string or a number, not 'list'
```
```python
import numpy as np
a = np.random.rand(5)
a[0] = [3.14]
```
```
ValueError: setting an array element with a sequence.
```
Fixes #10404.
Diffstat (limited to 'numpy/core/src/multiarray')
-rw-r--r-- | numpy/core/src/multiarray/common.c | 29 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.h | 7 | ||||
-rw-r--r-- | numpy/core/src/multiarray/methods.c | 4 | ||||
-rw-r--r-- | numpy/core/src/multiarray/number.c | 6 |
4 files changed, 39 insertions, 7 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index 001d299c7..573d0d606 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -441,3 +441,32 @@ new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out, } } +NPY_NO_EXPORT int +check_is_convertible_to_scalar(PyArrayObject *v) +{ + if (PyArray_NDIM(v) == 0) { + return 0; + } + + /* Remove this if-else block when the deprecation expires */ + if (PyArray_SIZE(v) == 1) { + /* Numpy 1.25.0, 2023-01-02 */ + if (DEPRECATE( + "Conversion of an array with ndim > 0 to a scalar " + "is deprecated, and will error in future. " + "Ensure you extract a single element from your array " + "before performing this operation. " + "(Deprecated NumPy 1.25.)") < 0) { + return -1; + } + return 0; + } else { + PyErr_SetString(PyExc_TypeError, + "only length-1 arrays can be converted to Python scalars"); + return -1; + } + + PyErr_SetString(PyExc_TypeError, + "only 0-dimensional arrays can be converted to Python scalars"); + return -1; +} diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index 127c6250d..cb9fadc4e 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -332,6 +332,13 @@ PyArray_TupleFromItems(int n, PyObject *const *items, int make_null_none) return tuple; } +/* + * Returns 0 if the array has rank 0, -1 otherwise. Prints a deprecation + * warning for arrays of _size_ 1. + */ +NPY_NO_EXPORT int +check_is_convertible_to_scalar(PyArrayObject *v); + #include "ucsnarrow.h" diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index 93b290020..3b2e72820 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -2804,9 +2804,7 @@ array_complex(PyArrayObject *self, PyObject *NPY_UNUSED(args)) PyArray_Descr *dtype; PyObject *c; - if (PyArray_SIZE(self) != 1) { - PyErr_SetString(PyExc_TypeError, - "only length-1 arrays can be converted to Python scalars"); + if (check_is_convertible_to_scalar(self) < 0) { return NULL; } diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index c208fb203..35e4af79c 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -869,13 +869,11 @@ array_scalar_forward(PyArrayObject *v, PyObject *(*builtin_func)(PyObject *), const char *where) { - PyObject *scalar; - if (PyArray_SIZE(v) != 1) { - PyErr_SetString(PyExc_TypeError, "only size-1 arrays can be"\ - " converted to Python scalars"); + if (check_is_convertible_to_scalar(v) < 0) { return NULL; } + PyObject *scalar; scalar = PyArray_GETITEM(v, PyArray_DATA(v)); if (scalar == NULL) { return NULL; |