Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

inconsistent string formating #4702

Open
dabidan opened this Issue May 12, 2014 · 1 comment

Comments

Projects
None yet
2 participants
Contributor

dabidan commented May 12, 2014

At string-formatting, the behaviour of 1x1-matrices is different, whether one uses str.format or %-formatting.

>>> x = numpy.array([[1.5]])
array([[ 1.5]])
>>> '%.3f' % x
'1.500'
>>> '{0:.3f}'.format(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'f' for object of type 'str'

Maybe provide custom formatting for matrices and not just str(...).
See also, solved issue #2271 for scalars.

mattayes commented May 29, 2016 edited

Running into this issue as well:

>>> import numpy as np
>>> x = np.array(1)
>>> '%0.f' % x
'5'
>>> format(x, ':0.f')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: non-empty format string passed to object.__format__

The error messages are also different for arrays of length 2 or more:

>>> y = np.array((1, 2))
>>> '%0.f' % y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: only length-1 arrays can be converted to Python scalars
>>> format(y, ':0.f')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: non-empty format string passed to object.__format__

Interestingly, the error message from % are even different than the messages you get when calling np.asscalaror y.item() (TypeError vs. ValueError)!

>>> np.asscalar(y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/python3.5/site-packages/numpy/lib/type_check.py", line 453, in asscalar
    return a.item()
ValueError: can only convert an array of size 1 to a Python scalar
>>> y.item()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: can only convert an array of size 1 to a Python scalar

Not sure why this is happening. Probably something to do with implementation differences between % formatting and format(). In any case, the __format__ method for np.ndarray should attempt to convert the array to a scalar, then format it:

class ndarray:
    ...
    def __format__(self, formatstr):
        try:
            # Try to convert the array to a scalar.
            scalar = self.item()
        except ValueError:
            # Can't be converted to a scalar, abort!
            return NotImplemented
        else:
            # If it doesn't explode, use the scalar's format method.
            return format(scalar, formatstr)
    ...

As mentioned on Stack Overflow, np.ndarray is actually an alias for multiarray, which is implemented in C. Not sure if that makes this a C issue or a Python issue. ¯_(ツ)_/¯

Willing to help on this if I can!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment