Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/_core/arrayprint.py: 19%
604 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-09 06:12 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-09 06:12 +0000
1"""Array printing function
3$Id: arrayprint.py,v 1.9 2005/09/13 13:58:44 teoliphant Exp $
5"""
6__all__ = ["array2string", "array_str", "array_repr",
7 "set_printoptions", "get_printoptions", "printoptions",
8 "format_float_positional", "format_float_scientific"]
9__docformat__ = 'restructuredtext'
11#
12# Written by Konrad Hinsen <hinsenk@ere.umontreal.ca>
13# last revision: 1996-3-13
14# modified by Jim Hugunin 1997-3-3 for repr's and str's (and other details)
15# and by Perry Greenfield 2000-4-1 for numarray
16# and by Travis Oliphant 2005-8-22 for numpy
19# Note: Both scalartypes.c.src and arrayprint.py implement strs for numpy
20# scalars but for different purposes. scalartypes.c.src has str/reprs for when
21# the scalar is printed on its own, while arrayprint.py has strs for when
22# scalars are printed inside an ndarray. Only the latter strs are currently
23# user-customizable.
25import functools
26import numbers
27import sys
28try:
29 from _thread import get_ident
30except ImportError:
31 from _dummy_thread import get_ident
33import numpy as np
34from . import numerictypes as _nt
35from .umath import absolute, isinf, isfinite, isnat
36from . import multiarray
37from .multiarray import (array, dragon4_positional, dragon4_scientific,
38 datetime_as_string, datetime_data, ndarray,
39 set_legacy_print_mode)
40from .fromnumeric import any
41from .numeric import concatenate, asarray, errstate
42from .numerictypes import (longlong, intc, int_, float64, complex128,
43 flexible)
44from .overrides import array_function_dispatch, set_module
45import operator
46import warnings
47import contextlib
49_format_options = {
50 'edgeitems': 3, # repr N leading and trailing items of each dimension
51 'threshold': 1000, # total items > triggers array summarization
52 'floatmode': 'maxprec',
53 'precision': 8, # precision of floating point representations
54 'suppress': False, # suppress printing small floating values in exp format
55 'linewidth': 75,
56 'nanstr': 'nan',
57 'infstr': 'inf',
58 'sign': '-',
59 'formatter': None,
60 # Internally stored as an int to simplify comparisons; converted from/to
61 # str/False on the way in/out.
62 'legacy': sys.maxsize}
64def _make_options_dict(precision=None, threshold=None, edgeitems=None,
65 linewidth=None, suppress=None, nanstr=None, infstr=None,
66 sign=None, formatter=None, floatmode=None, legacy=None):
67 """
68 Make a dictionary out of the non-None arguments, plus conversion of
69 *legacy* and sanity checks.
70 """
72 options = {k: v for k, v in list(locals().items()) if v is not None}
74 if suppress is not None:
75 options['suppress'] = bool(suppress)
77 modes = ['fixed', 'unique', 'maxprec', 'maxprec_equal']
78 if floatmode not in modes + [None]:
79 raise ValueError("floatmode option must be one of " +
80 ", ".join('"{}"'.format(m) for m in modes))
82 if sign not in [None, '-', '+', ' ']:
83 raise ValueError("sign option must be one of ' ', '+', or '-'")
85 if legacy == False:
86 options['legacy'] = sys.maxsize
87 elif legacy == '1.13':
88 options['legacy'] = 113
89 elif legacy == '1.21':
90 options['legacy'] = 121
91 elif legacy == '1.25':
92 options['legacy'] = 125
93 elif legacy is None:
94 pass # OK, do nothing.
95 else:
96 warnings.warn(
97 "legacy printing option can currently only be '1.13', '1.21', "
98 "'1.25', or `False`", stacklevel=3)
100 if threshold is not None:
101 # forbid the bad threshold arg suggested by stack overflow, gh-12351
102 if not isinstance(threshold, numbers.Number):
103 raise TypeError("threshold must be numeric")
104 if np.isnan(threshold):
105 raise ValueError("threshold must be non-NAN, try "
106 "sys.maxsize for untruncated representation")
108 if precision is not None:
109 # forbid the bad precision arg as suggested by issue #18254
110 try:
111 options['precision'] = operator.index(precision)
112 except TypeError as e:
113 raise TypeError('precision must be an integer') from e
115 return options
118@set_module('numpy')
119def set_printoptions(precision=None, threshold=None, edgeitems=None,
120 linewidth=None, suppress=None, nanstr=None,
121 infstr=None, formatter=None, sign=None, floatmode=None,
122 *, legacy=None):
123 """
124 Set printing options.
126 These options determine the way floating point numbers, arrays and
127 other NumPy objects are displayed.
129 Parameters
130 ----------
131 precision : int or None, optional
132 Number of digits of precision for floating point output (default 8).
133 May be None if `floatmode` is not `fixed`, to print as many digits as
134 necessary to uniquely specify the value.
135 threshold : int, optional
136 Total number of array elements which trigger summarization
137 rather than full repr (default 1000).
138 To always use the full repr without summarization, pass `sys.maxsize`.
139 edgeitems : int, optional
140 Number of array items in summary at beginning and end of
141 each dimension (default 3).
142 linewidth : int, optional
143 The number of characters per line for the purpose of inserting
144 line breaks (default 75).
145 suppress : bool, optional
146 If True, always print floating point numbers using fixed point
147 notation, in which case numbers equal to zero in the current precision
148 will print as zero. If False, then scientific notation is used when
149 absolute value of the smallest number is < 1e-4 or the ratio of the
150 maximum absolute value to the minimum is > 1e3. The default is False.
151 nanstr : str, optional
152 String representation of floating point not-a-number (default nan).
153 infstr : str, optional
154 String representation of floating point infinity (default inf).
155 sign : string, either '-', '+', or ' ', optional
156 Controls printing of the sign of floating-point types. If '+', always
157 print the sign of positive values. If ' ', always prints a space
158 (whitespace character) in the sign position of positive values. If
159 '-', omit the sign character of positive values. (default '-')
161 .. versionchanged:: 2.0
162 The sign parameter can now be an integer type, previously
163 types were floating-point types.
165 formatter : dict of callables, optional
166 If not None, the keys should indicate the type(s) that the respective
167 formatting function applies to. Callables should return a string.
168 Types that are not specified (by their corresponding keys) are handled
169 by the default formatters. Individual types for which a formatter
170 can be set are:
172 - 'bool'
173 - 'int'
174 - 'timedelta' : a `numpy.timedelta64`
175 - 'datetime' : a `numpy.datetime64`
176 - 'float'
177 - 'longfloat' : 128-bit floats
178 - 'complexfloat'
179 - 'longcomplexfloat' : composed of two 128-bit floats
180 - 'numpystr' : types `numpy.bytes_` and `numpy.str_`
181 - 'object' : `np.object_` arrays
183 Other keys that can be used to set a group of types at once are:
185 - 'all' : sets all types
186 - 'int_kind' : sets 'int'
187 - 'float_kind' : sets 'float' and 'longfloat'
188 - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
189 - 'str_kind' : sets 'numpystr'
190 floatmode : str, optional
191 Controls the interpretation of the `precision` option for
192 floating-point types. Can take the following values
193 (default maxprec_equal):
195 * 'fixed': Always print exactly `precision` fractional digits,
196 even if this would print more or fewer digits than
197 necessary to specify the value uniquely.
198 * 'unique': Print the minimum number of fractional digits necessary
199 to represent each value uniquely. Different elements may
200 have a different number of digits. The value of the
201 `precision` option is ignored.
202 * 'maxprec': Print at most `precision` fractional digits, but if
203 an element can be uniquely represented with fewer digits
204 only print it with that many.
205 * 'maxprec_equal': Print at most `precision` fractional digits,
206 but if every element in the array can be uniquely
207 represented with an equal number of fewer digits, use that
208 many digits for all elements.
209 legacy : string or `False`, optional
210 If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This
211 approximates numpy 1.13 print output by including a space in the sign
212 position of floats and different behavior for 0d arrays. This also
213 enables 1.21 legacy printing mode (described below).
215 If set to the string ``'1.21'`` enables 1.21 legacy printing mode. This
216 approximates numpy 1.21 print output of complex structured dtypes
217 by not inserting spaces after commas that separate fields and after
218 colons.
220 If set to `False`, disables legacy mode.
222 Unrecognized strings will be ignored with a warning for forward
223 compatibility.
225 .. versionadded:: 1.14.0
226 .. versionchanged:: 1.22.0
228 See Also
229 --------
230 get_printoptions, printoptions, array2string
232 Notes
233 -----
234 `formatter` is always reset with a call to `set_printoptions`.
236 Use `printoptions` as a context manager to set the values temporarily.
238 Examples
239 --------
240 Floating point precision can be set:
242 >>> np.set_printoptions(precision=4)
243 >>> np.array([1.123456789])
244 [1.1235]
246 Long arrays can be summarised:
248 >>> np.set_printoptions(threshold=5)
249 >>> np.arange(10)
250 array([0, 1, 2, ..., 7, 8, 9])
252 Small results can be suppressed:
254 >>> eps = np.finfo(float).eps
255 >>> x = np.arange(4.)
256 >>> x**2 - (x + eps)**2
257 array([-4.9304e-32, -4.4409e-16, 0.0000e+00, 0.0000e+00])
258 >>> np.set_printoptions(suppress=True)
259 >>> x**2 - (x + eps)**2
260 array([-0., -0., 0., 0.])
262 A custom formatter can be used to display array elements as desired:
264 >>> np.set_printoptions(formatter={'all':lambda x: 'int: '+str(-x)})
265 >>> x = np.arange(3)
266 >>> x
267 array([int: 0, int: -1, int: -2])
268 >>> np.set_printoptions() # formatter gets reset
269 >>> x
270 array([0, 1, 2])
272 To put back the default options, you can use:
274 >>> np.set_printoptions(edgeitems=3, infstr='inf',
275 ... linewidth=75, nanstr='nan', precision=8,
276 ... suppress=False, threshold=1000, formatter=None)
278 Also to temporarily override options, use `printoptions`
279 as a context manager:
281 >>> with np.printoptions(precision=2, suppress=True, threshold=5):
282 ... np.linspace(0, 10, 10)
283 array([ 0. , 1.11, 2.22, ..., 7.78, 8.89, 10. ])
285 """
286 opt = _make_options_dict(precision, threshold, edgeitems, linewidth,
287 suppress, nanstr, infstr, sign, formatter,
288 floatmode, legacy)
289 # formatter is always reset
290 opt['formatter'] = formatter
291 _format_options.update(opt)
293 # set the C variable for legacy mode
294 if _format_options['legacy'] == 113:
295 set_legacy_print_mode(113)
296 # reset the sign option in legacy mode to avoid confusion
297 _format_options['sign'] = '-'
298 elif _format_options['legacy'] == 121:
299 set_legacy_print_mode(121)
300 elif _format_options['legacy'] == 125:
301 set_legacy_print_mode(125)
302 elif _format_options['legacy'] == sys.maxsize:
303 set_legacy_print_mode(0)
306@set_module('numpy')
307def get_printoptions():
308 """
309 Return the current print options.
311 Returns
312 -------
313 print_opts : dict
314 Dictionary of current print options with keys
316 - precision : int
317 - threshold : int
318 - edgeitems : int
319 - linewidth : int
320 - suppress : bool
321 - nanstr : str
322 - infstr : str
323 - formatter : dict of callables
324 - sign : str
326 For a full description of these options, see `set_printoptions`.
328 See Also
329 --------
330 set_printoptions, printoptions
332 """
333 opts = _format_options.copy()
334 opts['legacy'] = {
335 113: '1.13', 121: '1.21', 125: '1.25', sys.maxsize: False,
336 }[opts['legacy']]
337 return opts
340def _get_legacy_print_mode():
341 """Return the legacy print mode as an int."""
342 return _format_options['legacy']
345@set_module('numpy')
346@contextlib.contextmanager
347def printoptions(*args, **kwargs):
348 """Context manager for setting print options.
350 Set print options for the scope of the `with` block, and restore the old
351 options at the end. See `set_printoptions` for the full description of
352 available options.
354 Examples
355 --------
357 >>> from numpy.testing import assert_equal
358 >>> with np.printoptions(precision=2):
359 ... np.array([2.0]) / 3
360 array([0.67])
362 The `as`-clause of the `with`-statement gives the current print options:
364 >>> with np.printoptions(precision=2) as opts:
365 ... assert_equal(opts, np.get_printoptions())
367 See Also
368 --------
369 set_printoptions, get_printoptions
371 """
372 opts = np.get_printoptions()
373 try:
374 np.set_printoptions(*args, **kwargs)
375 yield np.get_printoptions()
376 finally:
377 np.set_printoptions(**opts)
380def _leading_trailing(a, edgeitems, index=()):
381 """
382 Keep only the N-D corners (leading and trailing edges) of an array.
384 Should be passed a base-class ndarray, since it makes no guarantees about
385 preserving subclasses.
386 """
387 axis = len(index)
388 if axis == a.ndim:
389 return a[index]
391 if a.shape[axis] > 2*edgeitems:
392 return concatenate((
393 _leading_trailing(a, edgeitems, index + np.index_exp[:edgeitems]),
394 _leading_trailing(a, edgeitems, index + np.index_exp[-edgeitems:])
395 ), axis=axis)
396 else:
397 return _leading_trailing(a, edgeitems, index + np.index_exp[:])
400def _object_format(o):
401 """ Object arrays containing lists should be printed unambiguously """
402 if type(o) is list:
403 fmt = 'list({!r})'
404 else:
405 fmt = '{!r}'
406 return fmt.format(o)
408def repr_format(x):
409 if isinstance(x, (np.str_, np.bytes_)):
410 return repr(x.item())
411 return repr(x)
413def str_format(x):
414 if isinstance(x, (np.str_, np.bytes_)):
415 return str(x.item())
416 return str(x)
418def _get_formatdict(data, *, precision, floatmode, suppress, sign, legacy,
419 formatter, **kwargs):
420 # note: extra arguments in kwargs are ignored
422 # wrapped in lambdas to avoid taking a code path
423 # with the wrong type of data
424 formatdict = {
425 'bool': lambda: BoolFormat(data),
426 'int': lambda: IntegerFormat(data, sign),
427 'float': lambda: FloatingFormat(
428 data, precision, floatmode, suppress, sign, legacy=legacy),
429 'longfloat': lambda: FloatingFormat(
430 data, precision, floatmode, suppress, sign, legacy=legacy),
431 'complexfloat': lambda: ComplexFloatingFormat(
432 data, precision, floatmode, suppress, sign, legacy=legacy),
433 'longcomplexfloat': lambda: ComplexFloatingFormat(
434 data, precision, floatmode, suppress, sign, legacy=legacy),
435 'datetime': lambda: DatetimeFormat(data, legacy=legacy),
436 'timedelta': lambda: TimedeltaFormat(data),
437 'object': lambda: _object_format,
438 'void': lambda: str_format,
439 'numpystr': lambda: repr_format}
441 # we need to wrap values in `formatter` in a lambda, so that the interface
442 # is the same as the above values.
443 def indirect(x):
444 return lambda: x
446 if formatter is not None:
447 fkeys = [k for k in formatter.keys() if formatter[k] is not None]
448 if 'all' in fkeys:
449 for key in formatdict.keys():
450 formatdict[key] = indirect(formatter['all'])
451 if 'int_kind' in fkeys:
452 for key in ['int']:
453 formatdict[key] = indirect(formatter['int_kind'])
454 if 'float_kind' in fkeys:
455 for key in ['float', 'longfloat']:
456 formatdict[key] = indirect(formatter['float_kind'])
457 if 'complex_kind' in fkeys:
458 for key in ['complexfloat', 'longcomplexfloat']:
459 formatdict[key] = indirect(formatter['complex_kind'])
460 if 'str_kind' in fkeys:
461 formatdict['numpystr'] = indirect(formatter['str_kind'])
462 for key in formatdict.keys():
463 if key in fkeys:
464 formatdict[key] = indirect(formatter[key])
466 return formatdict
468def _get_format_function(data, **options):
469 """
470 find the right formatting function for the dtype_
471 """
472 dtype_ = data.dtype
473 dtypeobj = dtype_.type
474 formatdict = _get_formatdict(data, **options)
475 if dtypeobj is None:
476 return formatdict["numpystr"]()
477 elif issubclass(dtypeobj, _nt.bool):
478 return formatdict['bool']()
479 elif issubclass(dtypeobj, _nt.integer):
480 if issubclass(dtypeobj, _nt.timedelta64):
481 return formatdict['timedelta']()
482 else:
483 return formatdict['int']()
484 elif issubclass(dtypeobj, _nt.floating):
485 if issubclass(dtypeobj, _nt.longdouble):
486 return formatdict['longfloat']()
487 else:
488 return formatdict['float']()
489 elif issubclass(dtypeobj, _nt.complexfloating):
490 if issubclass(dtypeobj, _nt.clongdouble):
491 return formatdict['longcomplexfloat']()
492 else:
493 return formatdict['complexfloat']()
494 elif issubclass(dtypeobj, (_nt.str_, _nt.bytes_)):
495 return formatdict['numpystr']()
496 elif issubclass(dtypeobj, _nt.datetime64):
497 return formatdict['datetime']()
498 elif issubclass(dtypeobj, _nt.object_):
499 return formatdict['object']()
500 elif issubclass(dtypeobj, _nt.void):
501 if dtype_.names is not None:
502 return StructuredVoidFormat.from_data(data, **options)
503 else:
504 return formatdict['void']()
505 else:
506 return formatdict['numpystr']()
509def _recursive_guard(fillvalue='...'):
510 """
511 Like the python 3.2 reprlib.recursive_repr, but forwards *args and **kwargs
513 Decorates a function such that if it calls itself with the same first
514 argument, it returns `fillvalue` instead of recursing.
516 Largely copied from reprlib.recursive_repr
517 """
519 def decorating_function(f):
520 repr_running = set()
522 @functools.wraps(f)
523 def wrapper(self, *args, **kwargs):
524 key = id(self), get_ident()
525 if key in repr_running:
526 return fillvalue
527 repr_running.add(key)
528 try:
529 return f(self, *args, **kwargs)
530 finally:
531 repr_running.discard(key)
533 return wrapper
535 return decorating_function
538# gracefully handle recursive calls, when object arrays contain themselves
539@_recursive_guard()
540def _array2string(a, options, separator=' ', prefix=""):
541 # The formatter __init__s in _get_format_function cannot deal with
542 # subclasses yet, and we also need to avoid recursion issues in
543 # _formatArray with subclasses which return 0d arrays in place of scalars
544 data = asarray(a)
545 if a.shape == ():
546 a = data
548 if a.size > options['threshold']:
549 summary_insert = "..."
550 data = _leading_trailing(data, options['edgeitems'])
551 else:
552 summary_insert = ""
554 # find the right formatting function for the array
555 format_function = _get_format_function(data, **options)
557 # skip over "["
558 next_line_prefix = " "
559 # skip over array(
560 next_line_prefix += " "*len(prefix)
562 lst = _formatArray(a, format_function, options['linewidth'],
563 next_line_prefix, separator, options['edgeitems'],
564 summary_insert, options['legacy'])
565 return lst
568def _array2string_dispatcher(
569 a, max_line_width=None, precision=None,
570 suppress_small=None, separator=None, prefix=None,
571 style=None, formatter=None, threshold=None,
572 edgeitems=None, sign=None, floatmode=None, suffix=None,
573 *, legacy=None):
574 return (a,)
577@array_function_dispatch(_array2string_dispatcher, module='numpy')
578def array2string(a, max_line_width=None, precision=None,
579 suppress_small=None, separator=' ', prefix="",
580 style=np._NoValue, formatter=None, threshold=None,
581 edgeitems=None, sign=None, floatmode=None, suffix="",
582 *, legacy=None):
583 """
584 Return a string representation of an array.
586 Parameters
587 ----------
588 a : ndarray
589 Input array.
590 max_line_width : int, optional
591 Inserts newlines if text is longer than `max_line_width`.
592 Defaults to ``numpy.get_printoptions()['linewidth']``.
593 precision : int or None, optional
594 Floating point precision.
595 Defaults to ``numpy.get_printoptions()['precision']``.
596 suppress_small : bool, optional
597 Represent numbers "very close" to zero as zero; default is False.
598 Very close is defined by precision: if the precision is 8, e.g.,
599 numbers smaller (in absolute value) than 5e-9 are represented as
600 zero.
601 Defaults to ``numpy.get_printoptions()['suppress']``.
602 separator : str, optional
603 Inserted between elements.
604 prefix : str, optional
605 suffix : str, optional
606 The length of the prefix and suffix strings are used to respectively
607 align and wrap the output. An array is typically printed as::
609 prefix + array2string(a) + suffix
611 The output is left-padded by the length of the prefix string, and
612 wrapping is forced at the column ``max_line_width - len(suffix)``.
613 It should be noted that the content of prefix and suffix strings are
614 not included in the output.
615 style : _NoValue, optional
616 Has no effect, do not use.
618 .. deprecated:: 1.14.0
619 formatter : dict of callables, optional
620 If not None, the keys should indicate the type(s) that the respective
621 formatting function applies to. Callables should return a string.
622 Types that are not specified (by their corresponding keys) are handled
623 by the default formatters. Individual types for which a formatter
624 can be set are:
626 - 'bool'
627 - 'int'
628 - 'timedelta' : a `numpy.timedelta64`
629 - 'datetime' : a `numpy.datetime64`
630 - 'float'
631 - 'longfloat' : 128-bit floats
632 - 'complexfloat'
633 - 'longcomplexfloat' : composed of two 128-bit floats
634 - 'void' : type `numpy.void`
635 - 'numpystr' : types `numpy.bytes_` and `numpy.str_`
637 Other keys that can be used to set a group of types at once are:
639 - 'all' : sets all types
640 - 'int_kind' : sets 'int'
641 - 'float_kind' : sets 'float' and 'longfloat'
642 - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
643 - 'str_kind' : sets 'numpystr'
644 threshold : int, optional
645 Total number of array elements which trigger summarization
646 rather than full repr.
647 Defaults to ``numpy.get_printoptions()['threshold']``.
648 edgeitems : int, optional
649 Number of array items in summary at beginning and end of
650 each dimension.
651 Defaults to ``numpy.get_printoptions()['edgeitems']``.
652 sign : string, either '-', '+', or ' ', optional
653 Controls printing of the sign of floating-point types. If '+', always
654 print the sign of positive values. If ' ', always prints a space
655 (whitespace character) in the sign position of positive values. If
656 '-', omit the sign character of positive values.
657 Defaults to ``numpy.get_printoptions()['sign']``.
659 .. versionchanged:: 2.0
660 The sign parameter can now be an integer type, previously
661 types were floating-point types.
663 floatmode : str, optional
664 Controls the interpretation of the `precision` option for
665 floating-point types.
666 Defaults to ``numpy.get_printoptions()['floatmode']``.
667 Can take the following values:
669 - 'fixed': Always print exactly `precision` fractional digits,
670 even if this would print more or fewer digits than
671 necessary to specify the value uniquely.
672 - 'unique': Print the minimum number of fractional digits necessary
673 to represent each value uniquely. Different elements may
674 have a different number of digits. The value of the
675 `precision` option is ignored.
676 - 'maxprec': Print at most `precision` fractional digits, but if
677 an element can be uniquely represented with fewer digits
678 only print it with that many.
679 - 'maxprec_equal': Print at most `precision` fractional digits,
680 but if every element in the array can be uniquely
681 represented with an equal number of fewer digits, use that
682 many digits for all elements.
683 legacy : string or `False`, optional
684 If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This
685 approximates numpy 1.13 print output by including a space in the sign
686 position of floats and different behavior for 0d arrays. If set to
687 `False`, disables legacy mode. Unrecognized strings will be ignored
688 with a warning for forward compatibility.
690 .. versionadded:: 1.14.0
692 Returns
693 -------
694 array_str : str
695 String representation of the array.
697 Raises
698 ------
699 TypeError
700 if a callable in `formatter` does not return a string.
702 See Also
703 --------
704 array_str, array_repr, set_printoptions, get_printoptions
706 Notes
707 -----
708 If a formatter is specified for a certain type, the `precision` keyword is
709 ignored for that type.
711 This is a very flexible function; `array_repr` and `array_str` are using
712 `array2string` internally so keywords with the same name should work
713 identically in all three functions.
715 Examples
716 --------
717 >>> x = np.array([1e-16,1,2,3])
718 >>> np.array2string(x, precision=2, separator=',',
719 ... suppress_small=True)
720 '[0.,1.,2.,3.]'
722 >>> x = np.arange(3.)
723 >>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x})
724 '[0.00 1.00 2.00]'
726 >>> x = np.arange(3)
727 >>> np.array2string(x, formatter={'int':lambda x: hex(x)})
728 '[0x0 0x1 0x2]'
730 """
732 overrides = _make_options_dict(precision, threshold, edgeitems,
733 max_line_width, suppress_small, None, None,
734 sign, formatter, floatmode, legacy)
735 options = _format_options.copy()
736 options.update(overrides)
738 if options['legacy'] <= 113:
739 if style is np._NoValue:
740 style = repr
742 if a.shape == () and a.dtype.names is None:
743 return style(a.item())
744 elif style is not np._NoValue:
745 # Deprecation 11-9-2017 v1.14
746 warnings.warn("'style' argument is deprecated and no longer functional"
747 " except in 1.13 'legacy' mode",
748 DeprecationWarning, stacklevel=2)
750 if options['legacy'] > 113:
751 options['linewidth'] -= len(suffix)
753 # treat as a null array if any of shape elements == 0
754 if a.size == 0:
755 return "[]"
757 return _array2string(a, options, separator, prefix)
760def _extendLine(s, line, word, line_width, next_line_prefix, legacy):
761 needs_wrap = len(line) + len(word) > line_width
762 if legacy > 113:
763 # don't wrap lines if it won't help
764 if len(line) <= len(next_line_prefix):
765 needs_wrap = False
767 if needs_wrap:
768 s += line.rstrip() + "\n"
769 line = next_line_prefix
770 line += word
771 return s, line
774def _extendLine_pretty(s, line, word, line_width, next_line_prefix, legacy):
775 """
776 Extends line with nicely formatted (possibly multi-line) string ``word``.
777 """
778 words = word.splitlines()
779 if len(words) == 1 or legacy <= 113:
780 return _extendLine(s, line, word, line_width, next_line_prefix, legacy)
782 max_word_length = max(len(word) for word in words)
783 if (len(line) + max_word_length > line_width and
784 len(line) > len(next_line_prefix)):
785 s += line.rstrip() + '\n'
786 line = next_line_prefix + words[0]
787 indent = next_line_prefix
788 else:
789 indent = len(line)*' '
790 line += words[0]
792 for word in words[1::]:
793 s += line.rstrip() + '\n'
794 line = indent + word
796 suffix_length = max_word_length - len(words[-1])
797 line += suffix_length*' '
799 return s, line
801def _formatArray(a, format_function, line_width, next_line_prefix,
802 separator, edge_items, summary_insert, legacy):
803 """formatArray is designed for two modes of operation:
805 1. Full output
807 2. Summarized output
809 """
810 def recurser(index, hanging_indent, curr_width):
811 """
812 By using this local function, we don't need to recurse with all the
813 arguments. Since this function is not created recursively, the cost is
814 not significant
815 """
816 axis = len(index)
817 axes_left = a.ndim - axis
819 if axes_left == 0:
820 return format_function(a[index])
822 # when recursing, add a space to align with the [ added, and reduce the
823 # length of the line by 1
824 next_hanging_indent = hanging_indent + ' '
825 if legacy <= 113:
826 next_width = curr_width
827 else:
828 next_width = curr_width - len(']')
830 a_len = a.shape[axis]
831 show_summary = summary_insert and 2*edge_items < a_len
832 if show_summary:
833 leading_items = edge_items
834 trailing_items = edge_items
835 else:
836 leading_items = 0
837 trailing_items = a_len
839 # stringify the array with the hanging indent on the first line too
840 s = ''
842 # last axis (rows) - wrap elements if they would not fit on one line
843 if axes_left == 1:
844 # the length up until the beginning of the separator / bracket
845 if legacy <= 113:
846 elem_width = curr_width - len(separator.rstrip())
847 else:
848 elem_width = curr_width - max(
849 len(separator.rstrip()), len(']')
850 )
852 line = hanging_indent
853 for i in range(leading_items):
854 word = recurser(index + (i,), next_hanging_indent, next_width)
855 s, line = _extendLine_pretty(
856 s, line, word, elem_width, hanging_indent, legacy)
857 line += separator
859 if show_summary:
860 s, line = _extendLine(
861 s, line, summary_insert, elem_width, hanging_indent, legacy
862 )
863 if legacy <= 113:
864 line += ", "
865 else:
866 line += separator
868 for i in range(trailing_items, 1, -1):
869 word = recurser(index + (-i,), next_hanging_indent, next_width)
870 s, line = _extendLine_pretty(
871 s, line, word, elem_width, hanging_indent, legacy)
872 line += separator
874 if legacy <= 113:
875 # width of the separator is not considered on 1.13
876 elem_width = curr_width
877 word = recurser(index + (-1,), next_hanging_indent, next_width)
878 s, line = _extendLine_pretty(
879 s, line, word, elem_width, hanging_indent, legacy)
881 s += line
883 # other axes - insert newlines between rows
884 else:
885 s = ''
886 line_sep = separator.rstrip() + '\n'*(axes_left - 1)
888 for i in range(leading_items):
889 nested = recurser(
890 index + (i,), next_hanging_indent, next_width
891 )
892 s += hanging_indent + nested + line_sep
894 if show_summary:
895 if legacy <= 113:
896 # trailing space, fixed nbr of newlines,
897 # and fixed separator
898 s += hanging_indent + summary_insert + ", \n"
899 else:
900 s += hanging_indent + summary_insert + line_sep
902 for i in range(trailing_items, 1, -1):
903 nested = recurser(index + (-i,), next_hanging_indent,
904 next_width)
905 s += hanging_indent + nested + line_sep
907 nested = recurser(index + (-1,), next_hanging_indent, next_width)
908 s += hanging_indent + nested
910 # remove the hanging indent, and wrap in []
911 s = '[' + s[len(hanging_indent):] + ']'
912 return s
914 try:
915 # invoke the recursive part with an initial index and prefix
916 return recurser(index=(),
917 hanging_indent=next_line_prefix,
918 curr_width=line_width)
919 finally:
920 # recursive closures have a cyclic reference to themselves, which
921 # requires gc to collect (gh-10620). To avoid this problem, for
922 # performance and PyPy friendliness, we break the cycle:
923 recurser = None
925def _none_or_positive_arg(x, name):
926 if x is None:
927 return -1
928 if x < 0:
929 raise ValueError("{} must be >= 0".format(name))
930 return x
932class FloatingFormat:
933 """ Formatter for subtypes of np.floating """
934 def __init__(self, data, precision, floatmode, suppress_small, sign=False,
935 *, legacy=None):
936 # for backcompatibility, accept bools
937 if isinstance(sign, bool):
938 sign = '+' if sign else '-'
940 self._legacy = legacy
941 if self._legacy <= 113:
942 # when not 0d, legacy does not support '-'
943 if data.shape != () and sign == '-':
944 sign = ' '
946 self.floatmode = floatmode
947 if floatmode == 'unique':
948 self.precision = None
949 else:
950 self.precision = precision
952 self.precision = _none_or_positive_arg(self.precision, 'precision')
954 self.suppress_small = suppress_small
955 self.sign = sign
956 self.exp_format = False
957 self.large_exponent = False
959 self.fillFormat(data)
961 def fillFormat(self, data):
962 # only the finite values are used to compute the number of digits
963 finite_vals = data[isfinite(data)]
965 # choose exponential mode based on the non-zero finite values:
966 abs_non_zero = absolute(finite_vals[finite_vals != 0])
967 if len(abs_non_zero) != 0:
968 max_val = np.max(abs_non_zero)
969 min_val = np.min(abs_non_zero)
970 with errstate(over='ignore'): # division can overflow
971 if max_val >= 1.e8 or (not self.suppress_small and
972 (min_val < 0.0001 or max_val/min_val > 1000.)):
973 self.exp_format = True
975 # do a first pass of printing all the numbers, to determine sizes
976 if len(finite_vals) == 0:
977 self.pad_left = 0
978 self.pad_right = 0
979 self.trim = '.'
980 self.exp_size = -1
981 self.unique = True
982 self.min_digits = None
983 elif self.exp_format:
984 trim, unique = '.', True
985 if self.floatmode == 'fixed' or self._legacy <= 113:
986 trim, unique = 'k', False
987 strs = (dragon4_scientific(x, precision=self.precision,
988 unique=unique, trim=trim, sign=self.sign == '+')
989 for x in finite_vals)
990 frac_strs, _, exp_strs = zip(*(s.partition('e') for s in strs))
991 int_part, frac_part = zip(*(s.split('.') for s in frac_strs))
992 self.exp_size = max(len(s) for s in exp_strs) - 1
994 self.trim = 'k'
995 self.precision = max(len(s) for s in frac_part)
996 self.min_digits = self.precision
997 self.unique = unique
999 # for back-compat with np 1.13, use 2 spaces & sign and full prec
1000 if self._legacy <= 113:
1001 self.pad_left = 3
1002 else:
1003 # this should be only 1 or 2. Can be calculated from sign.
1004 self.pad_left = max(len(s) for s in int_part)
1005 # pad_right is only needed for nan length calculation
1006 self.pad_right = self.exp_size + 2 + self.precision
1007 else:
1008 trim, unique = '.', True
1009 if self.floatmode == 'fixed':
1010 trim, unique = 'k', False
1011 strs = (dragon4_positional(x, precision=self.precision,
1012 fractional=True,
1013 unique=unique, trim=trim,
1014 sign=self.sign == '+')
1015 for x in finite_vals)
1016 int_part, frac_part = zip(*(s.split('.') for s in strs))
1017 if self._legacy <= 113:
1018 self.pad_left = 1 + max(len(s.lstrip('-+')) for s in int_part)
1019 else:
1020 self.pad_left = max(len(s) for s in int_part)
1021 self.pad_right = max(len(s) for s in frac_part)
1022 self.exp_size = -1
1023 self.unique = unique
1025 if self.floatmode in ['fixed', 'maxprec_equal']:
1026 self.precision = self.min_digits = self.pad_right
1027 self.trim = 'k'
1028 else:
1029 self.trim = '.'
1030 self.min_digits = 0
1032 if self._legacy > 113:
1033 # account for sign = ' ' by adding one to pad_left
1034 if self.sign == ' ' and not any(np.signbit(finite_vals)):
1035 self.pad_left += 1
1037 # if there are non-finite values, may need to increase pad_left
1038 if data.size != finite_vals.size:
1039 neginf = self.sign != '-' or any(data[isinf(data)] < 0)
1040 nanlen = len(_format_options['nanstr'])
1041 inflen = len(_format_options['infstr']) + neginf
1042 offset = self.pad_right + 1 # +1 for decimal pt
1043 self.pad_left = max(
1044 self.pad_left, nanlen - offset, inflen - offset
1045 )
1047 def __call__(self, x):
1048 if not np.isfinite(x):
1049 with errstate(invalid='ignore'):
1050 if np.isnan(x):
1051 sign = '+' if self.sign == '+' else ''
1052 ret = sign + _format_options['nanstr']
1053 else: # isinf
1054 sign = '-' if x < 0 else '+' if self.sign == '+' else ''
1055 ret = sign + _format_options['infstr']
1056 return ' '*(
1057 self.pad_left + self.pad_right + 1 - len(ret)
1058 ) + ret
1060 if self.exp_format:
1061 return dragon4_scientific(x,
1062 precision=self.precision,
1063 min_digits=self.min_digits,
1064 unique=self.unique,
1065 trim=self.trim,
1066 sign=self.sign == '+',
1067 pad_left=self.pad_left,
1068 exp_digits=self.exp_size)
1069 else:
1070 return dragon4_positional(x,
1071 precision=self.precision,
1072 min_digits=self.min_digits,
1073 unique=self.unique,
1074 fractional=True,
1075 trim=self.trim,
1076 sign=self.sign == '+',
1077 pad_left=self.pad_left,
1078 pad_right=self.pad_right)
1081@set_module('numpy')
1082def format_float_scientific(x, precision=None, unique=True, trim='k',
1083 sign=False, pad_left=None, exp_digits=None,
1084 min_digits=None):
1085 """
1086 Format a floating-point scalar as a decimal string in scientific notation.
1088 Provides control over rounding, trimming and padding. Uses and assumes
1089 IEEE unbiased rounding. Uses the "Dragon4" algorithm.
1091 Parameters
1092 ----------
1093 x : python float or numpy floating scalar
1094 Value to format.
1095 precision : non-negative integer or None, optional
1096 Maximum number of digits to print. May be None if `unique` is
1097 `True`, but must be an integer if unique is `False`.
1098 unique : boolean, optional
1099 If `True`, use a digit-generation strategy which gives the shortest
1100 representation which uniquely identifies the floating-point number from
1101 other values of the same type, by judicious rounding. If `precision`
1102 is given fewer digits than necessary can be printed. If `min_digits`
1103 is given more can be printed, in which cases the last digit is rounded
1104 with unbiased rounding.
1105 If `False`, digits are generated as if printing an infinite-precision
1106 value and stopping after `precision` digits, rounding the remaining
1107 value with unbiased rounding
1108 trim : one of 'k', '.', '0', '-', optional
1109 Controls post-processing trimming of trailing digits, as follows:
1111 * 'k' : keep trailing zeros, keep decimal point (no trimming)
1112 * '.' : trim all trailing zeros, leave decimal point
1113 * '0' : trim all but the zero before the decimal point. Insert the
1114 zero if it is missing.
1115 * '-' : trim trailing zeros and any trailing decimal point
1116 sign : boolean, optional
1117 Whether to show the sign for positive values.
1118 pad_left : non-negative integer, optional
1119 Pad the left side of the string with whitespace until at least that
1120 many characters are to the left of the decimal point.
1121 exp_digits : non-negative integer, optional
1122 Pad the exponent with zeros until it contains at least this
1123 many digits. If omitted, the exponent will be at least 2 digits.
1124 min_digits : non-negative integer or None, optional
1125 Minimum number of digits to print. This only has an effect for
1126 `unique=True`. In that case more digits than necessary to uniquely
1127 identify the value may be printed and rounded unbiased.
1129 .. versionadded:: 1.21.0
1131 Returns
1132 -------
1133 rep : string
1134 The string representation of the floating point value
1136 See Also
1137 --------
1138 format_float_positional
1140 Examples
1141 --------
1142 >>> np.format_float_scientific(np.float32(np.pi))
1143 '3.1415927e+00'
1144 >>> s = np.float32(1.23e24)
1145 >>> np.format_float_scientific(s, unique=False, precision=15)
1146 '1.230000071797338e+24'
1147 >>> np.format_float_scientific(s, exp_digits=4)
1148 '1.23e+0024'
1149 """
1150 precision = _none_or_positive_arg(precision, 'precision')
1151 pad_left = _none_or_positive_arg(pad_left, 'pad_left')
1152 exp_digits = _none_or_positive_arg(exp_digits, 'exp_digits')
1153 min_digits = _none_or_positive_arg(min_digits, 'min_digits')
1154 if min_digits > 0 and precision > 0 and min_digits > precision:
1155 raise ValueError("min_digits must be less than or equal to precision")
1156 return dragon4_scientific(x, precision=precision, unique=unique,
1157 trim=trim, sign=sign, pad_left=pad_left,
1158 exp_digits=exp_digits, min_digits=min_digits)
1161@set_module('numpy')
1162def format_float_positional(x, precision=None, unique=True,
1163 fractional=True, trim='k', sign=False,
1164 pad_left=None, pad_right=None, min_digits=None):
1165 """
1166 Format a floating-point scalar as a decimal string in positional notation.
1168 Provides control over rounding, trimming and padding. Uses and assumes
1169 IEEE unbiased rounding. Uses the "Dragon4" algorithm.
1171 Parameters
1172 ----------
1173 x : python float or numpy floating scalar
1174 Value to format.
1175 precision : non-negative integer or None, optional
1176 Maximum number of digits to print. May be None if `unique` is
1177 `True`, but must be an integer if unique is `False`.
1178 unique : boolean, optional
1179 If `True`, use a digit-generation strategy which gives the shortest
1180 representation which uniquely identifies the floating-point number from
1181 other values of the same type, by judicious rounding. If `precision`
1182 is given fewer digits than necessary can be printed, or if `min_digits`
1183 is given more can be printed, in which cases the last digit is rounded
1184 with unbiased rounding.
1185 If `False`, digits are generated as if printing an infinite-precision
1186 value and stopping after `precision` digits, rounding the remaining
1187 value with unbiased rounding
1188 fractional : boolean, optional
1189 If `True`, the cutoffs of `precision` and `min_digits` refer to the
1190 total number of digits after the decimal point, including leading
1191 zeros.
1192 If `False`, `precision` and `min_digits` refer to the total number of
1193 significant digits, before or after the decimal point, ignoring leading
1194 zeros.
1195 trim : one of 'k', '.', '0', '-', optional
1196 Controls post-processing trimming of trailing digits, as follows:
1198 * 'k' : keep trailing zeros, keep decimal point (no trimming)
1199 * '.' : trim all trailing zeros, leave decimal point
1200 * '0' : trim all but the zero before the decimal point. Insert the
1201 zero if it is missing.
1202 * '-' : trim trailing zeros and any trailing decimal point
1203 sign : boolean, optional
1204 Whether to show the sign for positive values.
1205 pad_left : non-negative integer, optional
1206 Pad the left side of the string with whitespace until at least that
1207 many characters are to the left of the decimal point.
1208 pad_right : non-negative integer, optional
1209 Pad the right side of the string with whitespace until at least that
1210 many characters are to the right of the decimal point.
1211 min_digits : non-negative integer or None, optional
1212 Minimum number of digits to print. Only has an effect if `unique=True`
1213 in which case additional digits past those necessary to uniquely
1214 identify the value may be printed, rounding the last additional digit.
1216 .. versionadded:: 1.21.0
1218 Returns
1219 -------
1220 rep : string
1221 The string representation of the floating point value
1223 See Also
1224 --------
1225 format_float_scientific
1227 Examples
1228 --------
1229 >>> np.format_float_positional(np.float32(np.pi))
1230 '3.1415927'
1231 >>> np.format_float_positional(np.float16(np.pi))
1232 '3.14'
1233 >>> np.format_float_positional(np.float16(0.3))
1234 '0.3'
1235 >>> np.format_float_positional(np.float16(0.3), unique=False, precision=10)
1236 '0.3000488281'
1237 """
1238 precision = _none_or_positive_arg(precision, 'precision')
1239 pad_left = _none_or_positive_arg(pad_left, 'pad_left')
1240 pad_right = _none_or_positive_arg(pad_right, 'pad_right')
1241 min_digits = _none_or_positive_arg(min_digits, 'min_digits')
1242 if not fractional and precision == 0:
1243 raise ValueError("precision must be greater than 0 if "
1244 "fractional=False")
1245 if min_digits > 0 and precision > 0 and min_digits > precision:
1246 raise ValueError("min_digits must be less than or equal to precision")
1247 return dragon4_positional(x, precision=precision, unique=unique,
1248 fractional=fractional, trim=trim,
1249 sign=sign, pad_left=pad_left,
1250 pad_right=pad_right, min_digits=min_digits)
1252class IntegerFormat:
1253 def __init__(self, data, sign='-'):
1254 if data.size > 0:
1255 data_max = np.max(data)
1256 data_min = np.min(data)
1257 data_max_str_len = len(str(data_max))
1258 if sign == ' ' and data_min < 0:
1259 sign = '-'
1260 if data_max >= 0 and sign in "+ ":
1261 data_max_str_len += 1
1262 max_str_len = max(data_max_str_len,
1263 len(str(data_min)))
1264 else:
1265 max_str_len = 0
1266 self.format = f'{{:{sign}{max_str_len}d}}'
1268 def __call__(self, x):
1269 return self.format.format(x)
1271class BoolFormat:
1272 def __init__(self, data, **kwargs):
1273 # add an extra space so " True" and "False" have the same length and
1274 # array elements align nicely when printed, except in 0d arrays
1275 self.truestr = ' True' if data.shape != () else 'True'
1277 def __call__(self, x):
1278 return self.truestr if x else "False"
1281class ComplexFloatingFormat:
1282 """ Formatter for subtypes of np.complexfloating """
1283 def __init__(self, x, precision, floatmode, suppress_small,
1284 sign=False, *, legacy=None):
1285 # for backcompatibility, accept bools
1286 if isinstance(sign, bool):
1287 sign = '+' if sign else '-'
1289 floatmode_real = floatmode_imag = floatmode
1290 if legacy <= 113:
1291 floatmode_real = 'maxprec_equal'
1292 floatmode_imag = 'maxprec'
1294 self.real_format = FloatingFormat(
1295 x.real, precision, floatmode_real, suppress_small,
1296 sign=sign, legacy=legacy
1297 )
1298 self.imag_format = FloatingFormat(
1299 x.imag, precision, floatmode_imag, suppress_small,
1300 sign='+', legacy=legacy
1301 )
1303 def __call__(self, x):
1304 r = self.real_format(x.real)
1305 i = self.imag_format(x.imag)
1307 # add the 'j' before the terminal whitespace in i
1308 sp = len(i.rstrip())
1309 i = i[:sp] + 'j' + i[sp:]
1311 return r + i
1314class _TimelikeFormat:
1315 def __init__(self, data):
1316 non_nat = data[~isnat(data)]
1317 if len(non_nat) > 0:
1318 # Max str length of non-NaT elements
1319 max_str_len = max(len(self._format_non_nat(np.max(non_nat))),
1320 len(self._format_non_nat(np.min(non_nat))))
1321 else:
1322 max_str_len = 0
1323 if len(non_nat) < data.size:
1324 # data contains a NaT
1325 max_str_len = max(max_str_len, 5)
1326 self._format = '%{}s'.format(max_str_len)
1327 self._nat = "'NaT'".rjust(max_str_len)
1329 def _format_non_nat(self, x):
1330 # override in subclass
1331 raise NotImplementedError
1333 def __call__(self, x):
1334 if isnat(x):
1335 return self._nat
1336 else:
1337 return self._format % self._format_non_nat(x)
1340class DatetimeFormat(_TimelikeFormat):
1341 def __init__(self, x, unit=None, timezone=None, casting='same_kind',
1342 legacy=False):
1343 # Get the unit from the dtype
1344 if unit is None:
1345 if x.dtype.kind == 'M':
1346 unit = datetime_data(x.dtype)[0]
1347 else:
1348 unit = 's'
1350 if timezone is None:
1351 timezone = 'naive'
1352 self.timezone = timezone
1353 self.unit = unit
1354 self.casting = casting
1355 self.legacy = legacy
1357 # must be called after the above are configured
1358 super().__init__(x)
1360 def __call__(self, x):
1361 if self.legacy <= 113:
1362 return self._format_non_nat(x)
1363 return super().__call__(x)
1365 def _format_non_nat(self, x):
1366 return "'%s'" % datetime_as_string(x,
1367 unit=self.unit,
1368 timezone=self.timezone,
1369 casting=self.casting)
1372class TimedeltaFormat(_TimelikeFormat):
1373 def _format_non_nat(self, x):
1374 return str(x.astype('i8'))
1377class SubArrayFormat:
1378 def __init__(self, format_function, **options):
1379 self.format_function = format_function
1380 self.threshold = options['threshold']
1381 self.edge_items = options['edgeitems']
1383 def __call__(self, a):
1384 self.summary_insert = "..." if a.size > self.threshold else ""
1385 return self.format_array(a)
1387 def format_array(self, a):
1388 if np.ndim(a) == 0:
1389 return self.format_function(a)
1391 if self.summary_insert and a.shape[0] > 2*self.edge_items:
1392 formatted = (
1393 [self.format_array(a_) for a_ in a[:self.edge_items]]
1394 + [self.summary_insert]
1395 + [self.format_array(a_) for a_ in a[-self.edge_items:]]
1396 )
1397 else:
1398 formatted = [self.format_array(a_) for a_ in a]
1400 return "[" + ", ".join(formatted) + "]"
1403class StructuredVoidFormat:
1404 """
1405 Formatter for structured np.void objects.
1407 This does not work on structured alias types like
1408 np.dtype(('i4', 'i2,i2')), as alias scalars lose their field information,
1409 and the implementation relies upon np.void.__getitem__.
1410 """
1411 def __init__(self, format_functions):
1412 self.format_functions = format_functions
1414 @classmethod
1415 def from_data(cls, data, **options):
1416 """
1417 This is a second way to initialize StructuredVoidFormat,
1418 using the raw data as input. Added to avoid changing
1419 the signature of __init__.
1420 """
1421 format_functions = []
1422 for field_name in data.dtype.names:
1423 format_function = _get_format_function(data[field_name], **options)
1424 if data.dtype[field_name].shape != ():
1425 format_function = SubArrayFormat(format_function, **options)
1426 format_functions.append(format_function)
1427 return cls(format_functions)
1429 def __call__(self, x):
1430 str_fields = [
1431 format_function(field)
1432 for field, format_function in zip(x, self.format_functions)
1433 ]
1434 if len(str_fields) == 1:
1435 return "({},)".format(str_fields[0])
1436 else:
1437 return "({})".format(", ".join(str_fields))
1440def _void_scalar_to_string(x, is_repr=True):
1441 """
1442 Implements the repr for structured-void scalars. It is called from the
1443 scalartypes.c.src code, and is placed here because it uses the elementwise
1444 formatters defined above.
1445 """
1446 options = _format_options.copy()
1448 if options["legacy"] <= 125:
1449 return StructuredVoidFormat.from_data(array(x), **_format_options)(x)
1451 if options.get('formatter') is None:
1452 options['formatter'] = {}
1453 options['formatter'].setdefault('float_kind', str)
1454 val_repr = StructuredVoidFormat.from_data(array(x), **options)(x)
1455 if not is_repr:
1456 return val_repr
1457 cls = type(x)
1458 cls_fqn = cls.__module__.replace("numpy", "np") + "." + cls.__name__
1459 void_dtype = np.dtype((np.void, x.dtype))
1460 return f"{cls_fqn}({val_repr}, dtype={void_dtype!s})"
1463_typelessdata = [int_, float64, complex128, _nt.bool]
1466def dtype_is_implied(dtype):
1467 """
1468 Determine if the given dtype is implied by the representation
1469 of its values.
1471 Parameters
1472 ----------
1473 dtype : dtype
1474 Data type
1476 Returns
1477 -------
1478 implied : bool
1479 True if the dtype is implied by the representation of its values.
1481 Examples
1482 --------
1483 >>> np._core.arrayprint.dtype_is_implied(int)
1484 True
1485 >>> np.array([1, 2, 3], int)
1486 array([1, 2, 3])
1487 >>> np._core.arrayprint.dtype_is_implied(np.int8)
1488 False
1489 >>> np.array([1, 2, 3], np.int8)
1490 array([1, 2, 3], dtype=int8)
1491 """
1492 dtype = np.dtype(dtype)
1493 if _format_options['legacy'] <= 113 and dtype.type == np.bool:
1494 return False
1496 # not just void types can be structured, and names are not part of the repr
1497 if dtype.names is not None:
1498 return False
1500 # should care about endianness *unless size is 1* (e.g., int8, bool)
1501 if not dtype.isnative:
1502 return False
1504 return dtype.type in _typelessdata
1507def dtype_short_repr(dtype):
1508 """
1509 Convert a dtype to a short form which evaluates to the same dtype.
1511 The intent is roughly that the following holds
1513 >>> from numpy import *
1514 >>> dt = np.int64([1, 2]).dtype
1515 >>> assert eval(dtype_short_repr(dt)) == dt
1516 """
1517 if type(dtype).__repr__ != np.dtype.__repr__:
1518 # TODO: Custom repr for user DTypes, logic should likely move.
1519 return repr(dtype)
1520 if dtype.names is not None:
1521 # structured dtypes give a list or tuple repr
1522 return str(dtype)
1523 elif issubclass(dtype.type, flexible):
1524 # handle these separately so they don't give garbage like str256
1525 return "'%s'" % str(dtype)
1527 typename = dtype.name
1528 if not dtype.isnative:
1529 # deal with cases like dtype('<u2') that are identical to an
1530 # established dtype (in this case uint16)
1531 # except that they have a different endianness.
1532 return "'%s'" % str(dtype)
1533 # quote typenames which can't be represented as python variable names
1534 if typename and not (typename[0].isalpha() and typename.isalnum()):
1535 typename = repr(typename)
1536 return typename
1539def _array_repr_implementation(
1540 arr, max_line_width=None, precision=None, suppress_small=None,
1541 array2string=array2string):
1542 """Internal version of array_repr() that allows overriding array2string."""
1543 if max_line_width is None:
1544 max_line_width = _format_options['linewidth']
1546 if type(arr) is not ndarray:
1547 class_name = type(arr).__name__
1548 else:
1549 class_name = "array"
1551 skipdtype = dtype_is_implied(arr.dtype) and arr.size > 0
1553 prefix = class_name + "("
1554 suffix = ")" if skipdtype else ","
1556 if (_format_options['legacy'] <= 113 and
1557 arr.shape == () and not arr.dtype.names):
1558 lst = repr(arr.item())
1559 elif arr.size > 0 or arr.shape == (0,):
1560 lst = array2string(arr, max_line_width, precision, suppress_small,
1561 ', ', prefix, suffix=suffix)
1562 else: # show zero-length shape unless it is (0,)
1563 lst = "[], shape=%s" % (repr(arr.shape),)
1565 arr_str = prefix + lst + suffix
1567 if skipdtype:
1568 return arr_str
1570 dtype_str = "dtype={})".format(dtype_short_repr(arr.dtype))
1572 # compute whether we should put dtype on a new line: Do so if adding the
1573 # dtype would extend the last line past max_line_width.
1574 # Note: This line gives the correct result even when rfind returns -1.
1575 last_line_len = len(arr_str) - (arr_str.rfind('\n') + 1)
1576 spacer = " "
1577 if _format_options['legacy'] <= 113:
1578 if issubclass(arr.dtype.type, flexible):
1579 spacer = '\n' + ' '*len(class_name + "(")
1580 elif last_line_len + len(dtype_str) + 1 > max_line_width:
1581 spacer = '\n' + ' '*len(class_name + "(")
1583 return arr_str + spacer + dtype_str
1586def _array_repr_dispatcher(
1587 arr, max_line_width=None, precision=None, suppress_small=None):
1588 return (arr,)
1591@array_function_dispatch(_array_repr_dispatcher, module='numpy')
1592def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
1593 """
1594 Return the string representation of an array.
1596 Parameters
1597 ----------
1598 arr : ndarray
1599 Input array.
1600 max_line_width : int, optional
1601 Inserts newlines if text is longer than `max_line_width`.
1602 Defaults to ``numpy.get_printoptions()['linewidth']``.
1603 precision : int, optional
1604 Floating point precision.
1605 Defaults to ``numpy.get_printoptions()['precision']``.
1606 suppress_small : bool, optional
1607 Represent numbers "very close" to zero as zero; default is False.
1608 Very close is defined by precision: if the precision is 8, e.g.,
1609 numbers smaller (in absolute value) than 5e-9 are represented as
1610 zero.
1611 Defaults to ``numpy.get_printoptions()['suppress']``.
1613 Returns
1614 -------
1615 string : str
1616 The string representation of an array.
1618 See Also
1619 --------
1620 array_str, array2string, set_printoptions
1622 Examples
1623 --------
1624 >>> np.array_repr(np.array([1,2]))
1625 'array([1, 2])'
1626 >>> np.array_repr(np.ma.array([0.]))
1627 'MaskedArray([0.])'
1628 >>> np.array_repr(np.array([], np.int32))
1629 'array([], dtype=int32)'
1631 >>> x = np.array([1e-6, 4e-7, 2, 3])
1632 >>> np.array_repr(x, precision=6, suppress_small=True)
1633 'array([0.000001, 0. , 2. , 3. ])'
1635 """
1636 return _array_repr_implementation(
1637 arr, max_line_width, precision, suppress_small)
1640@_recursive_guard()
1641def _guarded_repr_or_str(v):
1642 if isinstance(v, bytes):
1643 return repr(v)
1644 return str(v)
1647def _array_str_implementation(
1648 a, max_line_width=None, precision=None, suppress_small=None,
1649 array2string=array2string):
1650 """Internal version of array_str() that allows overriding array2string."""
1651 if (_format_options['legacy'] <= 113 and
1652 a.shape == () and not a.dtype.names):
1653 return str(a.item())
1655 # the str of 0d arrays is a special case: It should appear like a scalar,
1656 # so floats are not truncated by `precision`, and strings are not wrapped
1657 # in quotes. So we return the str of the scalar value.
1658 if a.shape == ():
1659 # obtain a scalar and call str on it, avoiding problems for subclasses
1660 # for which indexing with () returns a 0d instead of a scalar by using
1661 # ndarray's getindex. Also guard against recursive 0d object arrays.
1662 return _guarded_repr_or_str(np.ndarray.__getitem__(a, ()))
1664 return array2string(a, max_line_width, precision, suppress_small, ' ', "")
1667def _array_str_dispatcher(
1668 a, max_line_width=None, precision=None, suppress_small=None):
1669 return (a,)
1672@array_function_dispatch(_array_str_dispatcher, module='numpy')
1673def array_str(a, max_line_width=None, precision=None, suppress_small=None):
1674 """
1675 Return a string representation of the data in an array.
1677 The data in the array is returned as a single string. This function is
1678 similar to `array_repr`, the difference being that `array_repr` also
1679 returns information on the kind of array and its data type.
1681 Parameters
1682 ----------
1683 a : ndarray
1684 Input array.
1685 max_line_width : int, optional
1686 Inserts newlines if text is longer than `max_line_width`.
1687 Defaults to ``numpy.get_printoptions()['linewidth']``.
1688 precision : int, optional
1689 Floating point precision.
1690 Defaults to ``numpy.get_printoptions()['precision']``.
1691 suppress_small : bool, optional
1692 Represent numbers "very close" to zero as zero; default is False.
1693 Very close is defined by precision: if the precision is 8, e.g.,
1694 numbers smaller (in absolute value) than 5e-9 are represented as
1695 zero.
1696 Defaults to ``numpy.get_printoptions()['suppress']``.
1698 See Also
1699 --------
1700 array2string, array_repr, set_printoptions
1702 Examples
1703 --------
1704 >>> np.array_str(np.arange(3))
1705 '[0 1 2]'
1707 """
1708 return _array_str_implementation(
1709 a, max_line_width, precision, suppress_small)
1712# needed if __array_function__ is disabled
1713_array2string_impl = getattr(array2string, '__wrapped__', array2string)
1714_default_array_str = functools.partial(_array_str_implementation,
1715 array2string=_array2string_impl)
1716_default_array_repr = functools.partial(_array_repr_implementation,
1717 array2string=_array2string_impl)
1720def set_string_function(f, repr=True):
1721 """
1722 Set a Python function to be used when pretty printing arrays.
1724 .. deprecated:: 2.0
1725 Use `np.set_printoptions` instead with a formatter for custom
1726 printing of NumPy objects.
1728 Parameters
1729 ----------
1730 f : function or None
1731 Function to be used to pretty print arrays. The function should expect
1732 a single array argument and return a string of the representation of
1733 the array. If None, the function is reset to the default NumPy function
1734 to print arrays.
1735 repr : bool, optional
1736 If True (default), the function for pretty printing (``__repr__``)
1737 is set, if False the function that returns the default string
1738 representation (``__str__``) is set.
1740 See Also
1741 --------
1742 set_printoptions, get_printoptions
1744 Examples
1745 --------
1746 >>> from numpy._core.arrayprint import set_string_function
1747 >>> def pprint(arr):
1748 ... return 'HA! - What are you going to do now?'
1749 ...
1750 >>> set_string_function(pprint)
1751 >>> a = np.arange(10)
1752 >>> a
1753 HA! - What are you going to do now?
1754 >>> _ = a
1755 >>> # [0 1 2 3 4 5 6 7 8 9]
1757 We can reset the function to the default:
1759 >>> set_string_function(None)
1760 >>> a
1761 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1763 `repr` affects either pretty printing or normal string representation.
1764 Note that ``__repr__`` is still affected by setting ``__str__``
1765 because the width of each array element in the returned string becomes
1766 equal to the length of the result of ``__str__()``.
1768 >>> x = np.arange(4)
1769 >>> set_string_function(lambda x:'random', repr=False)
1770 >>> x.__str__()
1771 'random'
1772 >>> x.__repr__()
1773 'array([0, 1, 2, 3])'
1775 """
1777 # Deprecated in NumPy 2.0, 2023-07-11
1778 warnings.warn(
1779 "`set_string_function` is deprecated. Use `np.set_printoptions` "
1780 "with a formatter for custom printing NumPy objects. "
1781 "(deprecated in NumPy 2.0)",
1782 DeprecationWarning,
1783 stacklevel=2
1784 )
1786 if f is None:
1787 if repr:
1788 return multiarray.set_string_function(_default_array_repr, 1)
1789 else:
1790 return multiarray.set_string_function(_default_array_str, 0)
1791 else:
1792 return multiarray.set_string_function(f, repr)