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