Repository: numpy/numpy
Pull request: DEP: deprecate asscalar
Closes #4701 (issue). Closes #11856 (PR). Closes #10256 (PR). Closes #10659 (PR).

This issue was labelled "easy" which led to the multiple PRs to fix it. I propose to deprecate it instead, as it is neither used nor tested in numpy, and is a thin wrapper to [`ndarray.item()`](http://www.numpy.org/devdocs/reference/generated/numpy.ndarray.item.html) but accepts none of the `args`.

SciPy does not use `asscalar`, astropy has two uses of `asscalar` which would need fixing.

Problem statement:
np.asscalar should pass through scalars
**Suggestion**
It would be very convenient if `np.asscalar()` would pass through scalars.  The use-case is to ensure that an argument is a scalar, regardless what is passed in (as long as it behaves as a scalar).

``` python
>>> np.asarray(1.0)
1.0
>>> np.asarray(1j)
1j
```

Presently these fail as the implementation simply looks for the `.item()` method, which scalars do not possess:

`````` python
>>> np.asarray(1.0)
AttributeError                            Traceback (most recent call last)
<ipython-input-13-c6bc08be135e> in <module>()
----> 1 np.asscalar(1.0)

.../python2.7/site-packages/numpy/lib/type_check.pyc in asscalar(a)
    461 
    462     """
--> 463     return a.item()
    464 
    465 #-----------------------------------------------------------------------------

AttributeError: 'float' object has no attribute 'item'```
``````

**Rational**
It is common to use `np.asarray()` to ensure that the argument is an array (in the case that it might be a list etc.).  In an analogous use case, it would be useful to be able to use `np.asscalar()` to ensure that an argument is a scalar (as long as it can be converted to a scalar).

**Workaround**
Convert the argument to an array first.

``` python
np.asscalar(np.asarray(x))
```

**Resolution**
Perhaps code like the following would work:

``` python
def asscalar(a):
    try:
        return a.item()
    except AttributeError, e:
        return np.asarray(a).item()
```

Hints from issue discussion:
I'd like to reopen this issue.  This is not fixed in numpy 1.13. It doesn't have the fix mentioned [here](https://github.com/numpy/numpy/pull/5126/files/525574d8da7133d3a4385dc30ada86b9cd1dd360#diff-e6c5cd017deafb358d97bcf913540a13)


```
In [4]: np.asscalar(3.4)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-8460cfbb0c19> in <module>()
----> 1 np.asscalar(3.4)

/home/foo/.virtualenv/myapp/lib/python2.7/site-packages/numpy/lib/type_check.pyc in asscalar(a)
    478 
    479     """
--> 480     return a.item()
    481 
    482 #-----------------------------------------------------------------------------

AttributeError: 'float' object has no attribute 'item'
```




```python
def asscalar(a):
    """
    Convert an array of size 1 to its scalar equivalent.

    Parameters
    ----------
    a : ndarray
        Input array of size 1.

    Returns
    -------
    out : scalar
        Scalar representation of `a`. The output data type is the same type
       returned by the input's `item` method.

    Examples
    --------
    >>> np.asscalar(np.array([24]))
    24

    """
    return a.item()

```
Looks like the wrong issue number was used in the commit that closed this
We need to make a decision on this before we get even more PRs attempting to "fix" it. To date:

* #11856 - open, plausible fix
* #10659 - open, plausible fix, has tests
* #10680 - closed. exact duplicate of #10659, no tests
* #10256 - open. _"This function strikes me as one in the "mistake we're now stuck with" category, which might be best to just leave alone."_ - me
* #5133 - closed, due to mangled history
* #5126 - closed, due to absent tests. _"Straight use of a.item() might be preferable to using the function."_ - @charris

Un-tagging as easy to stop us getting more of these
One of the main problems I have with `asscalar` is that it's just not consistent with `isscalar` - `isscalar(x)` currently does not imply `asscalar(x) is x`:
```python
>>> x = np.float64
>>> isscalar(x)
True
>>> type(x)
<class 'numpy.float64'>
>>> type(asscalar(x))
<class 'float'>
```

Overall, we have three conflicting definitions of scalar:

1. Is a python scalar - the type of object returned from `asscalar`
2. Is a python or numpy scalar - objects meeting `isscalar`
3. is a 0d array - `np.ndim(x) == 0`

Almost every time I see an internal use of `isscalar`, the intention was actually `np.ndim(x) == 0`. The exceptions are places that decide whether `*=` will modify in-place

Commit message: DEP: deprecate asscalar

Patch to review:
diff --git a/doc/release/1.16.0-notes.rst b/doc/release/1.16.0-notes.rst
index 72bf962953d1..9bd5e4f49697 100644
--- a/doc/release/1.16.0-notes.rst
+++ b/doc/release/1.16.0-notes.rst
@@ -36,6 +36,10 @@ and not documented. They will be removed in the 1.18 release. Use
 These were deprecated in 1.10, had no tests, and seem to no longer work in
 1.15 anyway.
 
+`numpy.asscalar` has been deprecated
+------------------------------------
+It is an alias to the more powerful `numpy.ndarray.item`, not tested, and fails
+for scalars.
 
 Future Changes
 ==============
diff --git a/numpy/lib/type_check.py b/numpy/lib/type_check.py
index 3f7aa32fa76c..8c79da7eb99d 100644
--- a/numpy/lib/type_check.py
+++ b/numpy/lib/type_check.py
@@ -2,6 +2,7 @@
 
 """
 from __future__ import division, absolute_import, print_function
+import warnings
 
 __all__ = ['iscomplexobj', 'isrealobj', 'imag', 'iscomplex',
            'isreal', 'nan_to_num', 'real', 'real_if_close',
@@ -469,6 +470,10 @@ def asscalar(a):
     """
     Convert an array of size 1 to its scalar equivalent.
 
+    .. deprecated:: 1.16
+
+        Deprecated, use `numpy.ndarray.item()` instead.
+
     Parameters
     ----------
     a : ndarray
@@ -486,6 +491,10 @@ def asscalar(a):
     24
 
     """
+
+    # 2018-10-10, 1.16
+    warnings.warn('np.asscalar(a) will be removed in v1.18 of numpy, use '
+                  'a.item() instead', DeprecationWarning, stacklevel=1)
     return a.item()
 
 #-----------------------------------------------------------------------------


Code review comments:
diff_hunk: @@ -486,6 +491,10 @@ def asscalar(a):
     24
 
     """
+
+    # 2018-10-10, 1.16
+    warnings.warn('np.asscalar(a) will be removed in v1.18 of numpy, use '
path: numpy/lib/type_check.py
text: @user1:
I think we are headed toward using the version deprecated rather than the version in which we intend to remove it. The latter may change, the first is fixed and helps folks downstream know how to set up version dependent workarounds.

@author:
Thanks for fixing