Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/numpy/_core/arrayprint.py: 17%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

605 statements  

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 

28 

29try: 

30 from _thread import get_ident 

31except ImportError: 

32 from _dummy_thread import get_ident 

33 

34import contextlib 

35import operator 

36import warnings 

37 

38import numpy as np 

39 

40from . import numerictypes as _nt 

41from .fromnumeric import any 

42from .multiarray import ( 

43 array, 

44 datetime_as_string, 

45 datetime_data, 

46 dragon4_positional, 

47 dragon4_scientific, 

48 ndarray, 

49) 

50from .numeric import asarray, concatenate, errstate 

51from .numerictypes import complex128, flexible, float64, int_ 

52from .overrides import array_function_dispatch, set_module 

53from .printoptions import format_options 

54from .umath import absolute, isfinite, isinf, isnat 

55 

56 

57def _make_options_dict(precision=None, threshold=None, edgeitems=None, 

58 linewidth=None, suppress=None, nanstr=None, infstr=None, 

59 sign=None, formatter=None, floatmode=None, legacy=None, 

60 override_repr=None): 

61 """ 

62 Make a dictionary out of the non-None arguments, plus conversion of 

63 *legacy* and sanity checks. 

64 """ 

65 

66 options = {k: v for k, v in list(locals().items()) if v is not None} 

67 

68 if suppress is not None: 

69 options['suppress'] = bool(suppress) 

70 

71 modes = ['fixed', 'unique', 'maxprec', 'maxprec_equal'] 

72 if floatmode not in modes + [None]: 

73 raise ValueError("floatmode option must be one of " + 

74 ", ".join(f'"{m}"' for m in modes)) 

75 

76 if sign not in [None, '-', '+', ' ']: 

77 raise ValueError("sign option must be one of ' ', '+', or '-'") 

78 

79 if legacy is False: 

80 options['legacy'] = sys.maxsize 

81 elif legacy == False: # noqa: E712 

82 warnings.warn( 

83 f"Passing `legacy={legacy!r}` is deprecated.", 

84 FutureWarning, stacklevel=3 

85 ) 

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 == '2.1': 

94 options['legacy'] = 201 

95 elif legacy == '2.2': 

96 options['legacy'] = 202 

97 elif legacy is None: 

98 pass # OK, do nothing. 

99 else: 

100 warnings.warn( 

101 "legacy printing option can currently only be '1.13', '1.21', " 

102 "'1.25', '2.1', '2.2' or `False`", stacklevel=3) 

103 

104 if threshold is not None: 

105 # forbid the bad threshold arg suggested by stack overflow, gh-12351 

106 if not isinstance(threshold, numbers.Number): 

107 raise TypeError("threshold must be numeric") 

108 if np.isnan(threshold): 

109 raise ValueError("threshold must be non-NAN, try " 

110 "sys.maxsize for untruncated representation") 

111 

112 if precision is not None: 

113 # forbid the bad precision arg as suggested by issue #18254 

114 try: 

115 options['precision'] = operator.index(precision) 

116 except TypeError as e: 

117 raise TypeError('precision must be an integer') from e 

118 

119 return options 

120 

121 

122@set_module('numpy') 

123def set_printoptions(precision=None, threshold=None, edgeitems=None, 

124 linewidth=None, suppress=None, nanstr=None, 

125 infstr=None, formatter=None, sign=None, floatmode=None, 

126 *, legacy=None, override_repr=None): 

127 """ 

128 Set printing options. 

129 

130 These options determine the way floating point numbers, arrays and 

131 other NumPy objects are displayed. 

132 

133 Parameters 

134 ---------- 

135 precision : int or None, optional 

136 Number of digits of precision for floating point output (default 8). 

137 May be None if `floatmode` is not `fixed`, to print as many digits as 

138 necessary to uniquely specify the value. 

139 threshold : int, optional 

140 Total number of array elements which trigger summarization 

141 rather than full repr (default 1000). 

142 To always use the full repr without summarization, pass `sys.maxsize`. 

143 edgeitems : int, optional 

144 Number of array items in summary at beginning and end of 

145 each dimension (default 3). 

146 linewidth : int, optional 

147 The number of characters per line for the purpose of inserting 

148 line breaks (default 75). 

149 suppress : bool, optional 

150 If True, always print floating point numbers using fixed point 

151 notation, in which case numbers equal to zero in the current precision 

152 will print as zero. If False, then scientific notation is used when 

153 absolute value of the smallest number is < 1e-4 or the ratio of the 

154 maximum absolute value to the minimum is > 1e3. The default is False. 

155 nanstr : str, optional 

156 String representation of floating point not-a-number (default nan). 

157 infstr : str, optional 

158 String representation of floating point infinity (default inf). 

159 sign : string, either '-', '+', or ' ', optional 

160 Controls printing of the sign of floating-point types. If '+', always 

161 print the sign of positive values. If ' ', always prints a space 

162 (whitespace character) in the sign position of positive values. If 

163 '-', omit the sign character of positive values. (default '-') 

164 

165 .. versionchanged:: 2.0 

166 The sign parameter can now be an integer type, previously 

167 types were floating-point types. 

168 

169 formatter : dict of callables, optional 

170 If not None, the keys should indicate the type(s) that the respective 

171 formatting function applies to. Callables should return a string. 

172 Types that are not specified (by their corresponding keys) are handled 

173 by the default formatters. Individual types for which a formatter 

174 can be set are: 

175 

176 - 'bool' 

177 - 'int' 

178 - 'timedelta' : a `numpy.timedelta64` 

179 - 'datetime' : a `numpy.datetime64` 

180 - 'float' 

181 - 'longfloat' : 128-bit floats 

182 - 'complexfloat' 

183 - 'longcomplexfloat' : composed of two 128-bit floats 

184 - 'numpystr' : types `numpy.bytes_` and `numpy.str_` 

185 - 'object' : `np.object_` arrays 

186 

187 Other keys that can be used to set a group of types at once are: 

188 

189 - 'all' : sets all types 

190 - 'int_kind' : sets 'int' 

191 - 'float_kind' : sets 'float' and 'longfloat' 

192 - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat' 

193 - 'str_kind' : sets 'numpystr' 

194 floatmode : str, optional 

195 Controls the interpretation of the `precision` option for 

196 floating-point types. Can take the following values 

197 (default maxprec_equal): 

198 

199 * 'fixed': Always print exactly `precision` fractional digits, 

200 even if this would print more or fewer digits than 

201 necessary to specify the value uniquely. 

202 * 'unique': Print the minimum number of fractional digits necessary 

203 to represent each value uniquely. Different elements may 

204 have a different number of digits. The value of the 

205 `precision` option is ignored. 

206 * 'maxprec': Print at most `precision` fractional digits, but if 

207 an element can be uniquely represented with fewer digits 

208 only print it with that many. 

209 * 'maxprec_equal': Print at most `precision` fractional digits, 

210 but if every element in the array can be uniquely 

211 represented with an equal number of fewer digits, use that 

212 many digits for all elements. 

213 legacy : string or `False`, optional 

214 If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This 

215 approximates numpy 1.13 print output by including a space in the sign 

216 position of floats and different behavior for 0d arrays. This also 

217 enables 1.21 legacy printing mode (described below). 

218 

219 If set to the string ``'1.21'`` enables 1.21 legacy printing mode. This 

220 approximates numpy 1.21 print output of complex structured dtypes 

221 by not inserting spaces after commas that separate fields and after 

222 colons. 

223 

224 If set to ``'1.25'`` approximates printing of 1.25 which mainly means 

225 that numeric scalars are printed without their type information, e.g. 

226 as ``3.0`` rather than ``np.float64(3.0)``. 

227 

228 If set to ``'2.1'``, shape information is not given when arrays are 

229 summarized (i.e., multiple elements replaced with ``...``). 

230 

231 If set to ``'2.2'``, the transition to use scientific notation for 

232 printing ``np.float16`` and ``np.float32`` types may happen later or 

233 not at all for larger values. 

234 

235 If set to `False`, disables legacy mode. 

236 

237 Unrecognized strings will be ignored with a warning for forward 

238 compatibility. 

239 

240 .. versionchanged:: 1.22.0 

241 .. versionchanged:: 2.2 

242 

243 override_repr: callable, optional 

244 If set a passed function will be used for generating arrays' repr. 

245 Other options will be ignored. 

246 

247 See Also 

248 -------- 

249 get_printoptions, printoptions, array2string 

250 

251 

252 Notes 

253 ----- 

254 

255 * ``formatter`` is always reset with a call to `set_printoptions`. 

256 * Use `printoptions` as a context manager to set the values temporarily. 

257 * These print options apply only to NumPy ndarrays, not to scalars. 

258 

259 **Concurrency note:** see :ref:`text_formatting_options` 

260 

261 Examples 

262 -------- 

263 Floating point precision can be set: 

264 

265 >>> import numpy as np 

266 >>> np.set_printoptions(precision=4) 

267 >>> np.array([1.123456789]) 

268 [1.1235] 

269 

270 Long arrays can be summarised: 

271 

272 >>> np.set_printoptions(threshold=5) 

273 >>> np.arange(10) 

274 array([0, 1, 2, ..., 7, 8, 9], shape=(10,)) 

275 

276 Small results can be suppressed: 

277 

278 >>> eps = np.finfo(float).eps 

279 >>> x = np.arange(4.) 

280 >>> x**2 - (x + eps)**2 

281 array([-4.9304e-32, -4.4409e-16, 0.0000e+00, 0.0000e+00]) 

282 >>> np.set_printoptions(suppress=True) 

283 >>> x**2 - (x + eps)**2 

284 array([-0., -0., 0., 0.]) 

285 

286 A custom formatter can be used to display array elements as desired: 

287 

288 >>> np.set_printoptions(formatter={'all':lambda x: 'int: '+str(-x)}) 

289 >>> x = np.arange(3) 

290 >>> x 

291 array([int: 0, int: -1, int: -2]) 

292 >>> np.set_printoptions() # formatter gets reset 

293 >>> x 

294 array([0, 1, 2]) 

295 

296 To put back the default options, you can use: 

297 

298 >>> np.set_printoptions(edgeitems=3, infstr='inf', 

299 ... linewidth=75, nanstr='nan', precision=8, 

300 ... suppress=False, threshold=1000, formatter=None) 

301 

302 Also to temporarily override options, use `printoptions` 

303 as a context manager: 

304 

305 >>> with np.printoptions(precision=2, suppress=True, threshold=5): 

306 ... np.linspace(0, 10, 10) 

307 array([ 0. , 1.11, 2.22, ..., 7.78, 8.89, 10. ], shape=(10,)) 

308 

309 """ 

310 _set_printoptions(precision, threshold, edgeitems, linewidth, suppress, 

311 nanstr, infstr, formatter, sign, floatmode, 

312 legacy=legacy, override_repr=override_repr) 

313 

314 

315def _set_printoptions(precision=None, threshold=None, edgeitems=None, 

316 linewidth=None, suppress=None, nanstr=None, 

317 infstr=None, formatter=None, sign=None, floatmode=None, 

318 *, legacy=None, override_repr=None): 

319 new_opt = _make_options_dict(precision, threshold, edgeitems, linewidth, 

320 suppress, nanstr, infstr, sign, formatter, 

321 floatmode, legacy) 

322 # formatter and override_repr are always reset 

323 new_opt['formatter'] = formatter 

324 new_opt['override_repr'] = override_repr 

325 

326 updated_opt = format_options.get() | new_opt 

327 updated_opt.update(new_opt) 

328 

329 if updated_opt['legacy'] == 113: 

330 updated_opt['sign'] = '-' 

331 

332 return format_options.set(updated_opt) 

333 

334 

335@set_module('numpy') 

336def get_printoptions(): 

337 """ 

338 Return the current print options. 

339 

340 Returns 

341 ------- 

342 print_opts : dict 

343 Dictionary of current print options with keys 

344 

345 - precision : int 

346 - threshold : int 

347 - edgeitems : int 

348 - linewidth : int 

349 - suppress : bool 

350 - nanstr : str 

351 - infstr : str 

352 - sign : str 

353 - formatter : dict of callables 

354 - floatmode : str 

355 - legacy : str or False 

356 

357 For a full description of these options, see `set_printoptions`. 

358 

359 Notes 

360 ----- 

361 These print options apply only to NumPy ndarrays, not to scalars. 

362 

363 **Concurrency note:** see :ref:`text_formatting_options` 

364 

365 See Also 

366 -------- 

367 set_printoptions, printoptions 

368 

369 Examples 

370 -------- 

371 >>> import numpy as np 

372 

373 >>> np.get_printoptions() 

374 {'edgeitems': 3, 'threshold': 1000, ..., 'override_repr': None} 

375 

376 >>> np.get_printoptions()['linewidth'] 

377 75 

378 >>> np.set_printoptions(linewidth=100) 

379 >>> np.get_printoptions()['linewidth'] 

380 100 

381 

382 """ 

383 opts = format_options.get().copy() 

384 opts['legacy'] = { 

385 113: '1.13', 121: '1.21', 125: '1.25', 201: '2.1', 

386 202: '2.2', sys.maxsize: False, 

387 }[opts['legacy']] 

388 return opts 

389 

390 

391def _get_legacy_print_mode(): 

392 """Return the legacy print mode as an int.""" 

393 return format_options.get()['legacy'] 

394 

395 

396@set_module('numpy') 

397@contextlib.contextmanager 

398def printoptions(*args, **kwargs): 

399 """Context manager for setting print options. 

400 

401 Set print options for the scope of the `with` block, and restore the old 

402 options at the end. See `set_printoptions` for the full description of 

403 available options. 

404 

405 Examples 

406 -------- 

407 >>> import numpy as np 

408 

409 >>> from numpy.testing import assert_equal 

410 >>> with np.printoptions(precision=2): 

411 ... np.array([2.0]) / 3 

412 array([0.67]) 

413 

414 The `as`-clause of the `with`-statement gives the current print options: 

415 

416 >>> with np.printoptions(precision=2) as opts: 

417 ... assert_equal(opts, np.get_printoptions()) 

418 

419 See Also 

420 -------- 

421 set_printoptions, get_printoptions 

422 

423 Notes 

424 ----- 

425 These print options apply only to NumPy ndarrays, not to scalars. 

426 

427 **Concurrency note:** see :ref:`text_formatting_options` 

428 

429 """ 

430 token = _set_printoptions(*args, **kwargs) 

431 

432 try: 

433 yield get_printoptions() 

434 finally: 

435 format_options.reset(token) 

436 

437 

438def _leading_trailing(a, edgeitems, index=()): 

439 """ 

440 Keep only the N-D corners (leading and trailing edges) of an array. 

441 

442 Should be passed a base-class ndarray, since it makes no guarantees about 

443 preserving subclasses. 

444 """ 

445 axis = len(index) 

446 if axis == a.ndim: 

447 return a[index] 

448 

449 if a.shape[axis] > 2 * edgeitems: 

450 return concatenate(( 

451 _leading_trailing(a, edgeitems, index + np.index_exp[:edgeitems]), 

452 _leading_trailing(a, edgeitems, index + np.index_exp[-edgeitems:]) 

453 ), axis=axis) 

454 else: 

455 return _leading_trailing(a, edgeitems, index + np.index_exp[:]) 

456 

457 

458def _object_format(o): 

459 """ Object arrays containing lists should be printed unambiguously """ 

460 if type(o) is list: 

461 fmt = 'list({!r})' 

462 else: 

463 fmt = '{!r}' 

464 return fmt.format(o) 

465 

466def repr_format(x): 

467 if isinstance(x, (np.str_, np.bytes_)): 

468 return repr(x.item()) 

469 return repr(x) 

470 

471def str_format(x): 

472 if isinstance(x, (np.str_, np.bytes_)): 

473 return str(x.item()) 

474 return str(x) 

475 

476def _get_formatdict(data, *, precision, floatmode, suppress, sign, legacy, 

477 formatter, **kwargs): 

478 # note: extra arguments in kwargs are ignored 

479 

480 # wrapped in lambdas to avoid taking a code path 

481 # with the wrong type of data 

482 formatdict = { 

483 'bool': lambda: BoolFormat(data), 

484 'int': lambda: IntegerFormat(data, sign), 

485 'float': lambda: FloatingFormat( 

486 data, precision, floatmode, suppress, sign, legacy=legacy), 

487 'longfloat': lambda: FloatingFormat( 

488 data, precision, floatmode, suppress, sign, legacy=legacy), 

489 'complexfloat': lambda: ComplexFloatingFormat( 

490 data, precision, floatmode, suppress, sign, legacy=legacy), 

491 'longcomplexfloat': lambda: ComplexFloatingFormat( 

492 data, precision, floatmode, suppress, sign, legacy=legacy), 

493 'datetime': lambda: DatetimeFormat(data, legacy=legacy), 

494 'timedelta': lambda: TimedeltaFormat(data), 

495 'object': lambda: _object_format, 

496 'void': lambda: str_format, 

497 'numpystr': lambda: repr_format} 

498 

499 # we need to wrap values in `formatter` in a lambda, so that the interface 

500 # is the same as the above values. 

501 def indirect(x): 

502 return lambda: x 

503 

504 if formatter is not None: 

505 fkeys = [k for k in formatter.keys() if formatter[k] is not None] 

506 if 'all' in fkeys: 

507 for key in formatdict.keys(): 

508 formatdict[key] = indirect(formatter['all']) 

509 if 'int_kind' in fkeys: 

510 for key in ['int']: 

511 formatdict[key] = indirect(formatter['int_kind']) 

512 if 'float_kind' in fkeys: 

513 for key in ['float', 'longfloat']: 

514 formatdict[key] = indirect(formatter['float_kind']) 

515 if 'complex_kind' in fkeys: 

516 for key in ['complexfloat', 'longcomplexfloat']: 

517 formatdict[key] = indirect(formatter['complex_kind']) 

518 if 'str_kind' in fkeys: 

519 formatdict['numpystr'] = indirect(formatter['str_kind']) 

520 for key in formatdict.keys(): 

521 if key in fkeys: 

522 formatdict[key] = indirect(formatter[key]) 

523 

524 return formatdict 

525 

526def _get_format_function(data, **options): 

527 """ 

528 find the right formatting function for the dtype_ 

529 """ 

530 dtype_ = data.dtype 

531 dtypeobj = dtype_.type 

532 formatdict = _get_formatdict(data, **options) 

533 if dtypeobj is None: 

534 return formatdict["numpystr"]() 

535 elif issubclass(dtypeobj, _nt.bool): 

536 return formatdict['bool']() 

537 elif issubclass(dtypeobj, _nt.integer): 

538 if issubclass(dtypeobj, _nt.timedelta64): 

539 return formatdict['timedelta']() 

540 else: 

541 return formatdict['int']() 

542 elif issubclass(dtypeobj, _nt.floating): 

543 if issubclass(dtypeobj, _nt.longdouble): 

544 return formatdict['longfloat']() 

545 else: 

546 return formatdict['float']() 

547 elif issubclass(dtypeobj, _nt.complexfloating): 

548 if issubclass(dtypeobj, _nt.clongdouble): 

549 return formatdict['longcomplexfloat']() 

550 else: 

551 return formatdict['complexfloat']() 

552 elif issubclass(dtypeobj, (_nt.str_, _nt.bytes_)): 

553 return formatdict['numpystr']() 

554 elif issubclass(dtypeobj, _nt.datetime64): 

555 return formatdict['datetime']() 

556 elif issubclass(dtypeobj, _nt.object_): 

557 return formatdict['object']() 

558 elif issubclass(dtypeobj, _nt.void): 

559 if dtype_.names is not None: 

560 return StructuredVoidFormat.from_data(data, **options) 

561 else: 

562 return formatdict['void']() 

563 else: 

564 return formatdict['numpystr']() 

565 

566 

567def _recursive_guard(fillvalue='...'): 

568 """ 

569 Like the python 3.2 reprlib.recursive_repr, but forwards *args and **kwargs 

570 

571 Decorates a function such that if it calls itself with the same first 

572 argument, it returns `fillvalue` instead of recursing. 

573 

574 Largely copied from reprlib.recursive_repr 

575 """ 

576 

577 def decorating_function(f): 

578 repr_running = set() 

579 

580 @functools.wraps(f) 

581 def wrapper(self, *args, **kwargs): 

582 key = id(self), get_ident() 

583 if key in repr_running: 

584 return fillvalue 

585 repr_running.add(key) 

586 try: 

587 return f(self, *args, **kwargs) 

588 finally: 

589 repr_running.discard(key) 

590 

591 return wrapper 

592 

593 return decorating_function 

594 

595 

596# gracefully handle recursive calls, when object arrays contain themselves 

597@_recursive_guard() 

598def _array2string(a, options, separator=' ', prefix=""): 

599 # The formatter __init__s in _get_format_function cannot deal with 

600 # subclasses yet, and we also need to avoid recursion issues in 

601 # _formatArray with subclasses which return 0d arrays in place of scalars 

602 data = asarray(a) 

603 if a.shape == (): 

604 a = data 

605 

606 if a.size > options['threshold']: 

607 summary_insert = "..." 

608 data = _leading_trailing(data, options['edgeitems']) 

609 else: 

610 summary_insert = "" 

611 

612 # find the right formatting function for the array 

613 format_function = _get_format_function(data, **options) 

614 

615 # skip over "[" 

616 next_line_prefix = " " 

617 # skip over array( 

618 next_line_prefix += " " * len(prefix) 

619 

620 lst = _formatArray(a, format_function, options['linewidth'], 

621 next_line_prefix, separator, options['edgeitems'], 

622 summary_insert, options['legacy']) 

623 return lst 

624 

625 

626def _array2string_dispatcher( 

627 a, max_line_width=None, precision=None, 

628 suppress_small=None, separator=None, prefix=None, 

629 *, formatter=None, threshold=None, 

630 edgeitems=None, sign=None, floatmode=None, suffix=None, 

631 legacy=None): 

632 return (a,) 

633 

634 

635@array_function_dispatch(_array2string_dispatcher, module='numpy') 

636def array2string(a, max_line_width=None, precision=None, 

637 suppress_small=None, separator=' ', prefix="", 

638 *, formatter=None, threshold=None, 

639 edgeitems=None, sign=None, floatmode=None, suffix="", 

640 legacy=None): 

641 """ 

642 Return a string representation of an array. 

643 

644 Parameters 

645 ---------- 

646 a : ndarray 

647 Input array. 

648 max_line_width : int, optional 

649 Inserts newlines if text is longer than `max_line_width`. 

650 Defaults to ``numpy.get_printoptions()['linewidth']``. 

651 precision : int or None, optional 

652 Floating point precision. 

653 Defaults to ``numpy.get_printoptions()['precision']``. 

654 suppress_small : bool, optional 

655 Represent numbers "very close" to zero as zero; default is False. 

656 Very close is defined by precision: if the precision is 8, e.g., 

657 numbers smaller (in absolute value) than 5e-9 are represented as 

658 zero. 

659 Defaults to ``numpy.get_printoptions()['suppress']``. 

660 separator : str, optional 

661 Inserted between elements. 

662 prefix : str, optional 

663 suffix : str, optional 

664 The length of the prefix and suffix strings are used to respectively 

665 align and wrap the output. An array is typically printed as:: 

666 

667 prefix + array2string(a) + suffix 

668 

669 The output is left-padded by the length of the prefix string, and 

670 wrapping is forced at the column ``max_line_width - len(suffix)``. 

671 It should be noted that the content of prefix and suffix strings are 

672 not included in the output. 

673 formatter : dict of callables, optional 

674 If not None, the keys should indicate the type(s) that the respective 

675 formatting function applies to. Callables should return a string. 

676 Types that are not specified (by their corresponding keys) are handled 

677 by the default formatters. Individual types for which a formatter 

678 can be set are: 

679 

680 - 'bool' 

681 - 'int' 

682 - 'timedelta' : a `numpy.timedelta64` 

683 - 'datetime' : a `numpy.datetime64` 

684 - 'float' 

685 - 'longfloat' : 128-bit floats 

686 - 'complexfloat' 

687 - 'longcomplexfloat' : composed of two 128-bit floats 

688 - 'void' : type `numpy.void` 

689 - 'numpystr' : types `numpy.bytes_` and `numpy.str_` 

690 

691 Other keys that can be used to set a group of types at once are: 

692 

693 - 'all' : sets all types 

694 - 'int_kind' : sets 'int' 

695 - 'float_kind' : sets 'float' and 'longfloat' 

696 - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat' 

697 - 'str_kind' : sets 'numpystr' 

698 threshold : int, optional 

699 Total number of array elements which trigger summarization 

700 rather than full repr. 

701 Defaults to ``numpy.get_printoptions()['threshold']``. 

702 edgeitems : int, optional 

703 Number of array items in summary at beginning and end of 

704 each dimension. 

705 Defaults to ``numpy.get_printoptions()['edgeitems']``. 

706 sign : string, either '-', '+', or ' ', optional 

707 Controls printing of the sign of floating-point types. If '+', always 

708 print the sign of positive values. If ' ', always prints a space 

709 (whitespace character) in the sign position of positive values. If 

710 '-', omit the sign character of positive values. 

711 Defaults to ``numpy.get_printoptions()['sign']``. 

712 

713 .. versionchanged:: 2.0 

714 The sign parameter can now be an integer type, previously 

715 types were floating-point types. 

716 

717 floatmode : str, optional 

718 Controls the interpretation of the `precision` option for 

719 floating-point types. 

720 Defaults to ``numpy.get_printoptions()['floatmode']``. 

721 Can take the following values: 

722 

723 - 'fixed': Always print exactly `precision` fractional digits, 

724 even if this would print more or fewer digits than 

725 necessary to specify the value uniquely. 

726 - 'unique': Print the minimum number of fractional digits necessary 

727 to represent each value uniquely. Different elements may 

728 have a different number of digits. The value of the 

729 `precision` option is ignored. 

730 - 'maxprec': Print at most `precision` fractional digits, but if 

731 an element can be uniquely represented with fewer digits 

732 only print it with that many. 

733 - 'maxprec_equal': Print at most `precision` fractional digits, 

734 but if every element in the array can be uniquely 

735 represented with an equal number of fewer digits, use that 

736 many digits for all elements. 

737 legacy : string or `False`, optional 

738 If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This 

739 approximates numpy 1.13 print output by including a space in the sign 

740 position of floats and different behavior for 0d arrays. If set to 

741 `False`, disables legacy mode. Unrecognized strings will be ignored 

742 with a warning for forward compatibility. 

743 

744 Returns 

745 ------- 

746 array_str : str 

747 String representation of the array. 

748 

749 Raises 

750 ------ 

751 TypeError 

752 if a callable in `formatter` does not return a string. 

753 

754 See Also 

755 -------- 

756 array_str, array_repr, set_printoptions, get_printoptions 

757 

758 Notes 

759 ----- 

760 If a formatter is specified for a certain type, the `precision` keyword is 

761 ignored for that type. 

762 

763 This is a very flexible function; `array_repr` and `array_str` are using 

764 `array2string` internally so keywords with the same name should work 

765 identically in all three functions. 

766 

767 Examples 

768 -------- 

769 >>> import numpy as np 

770 >>> x = np.array([1e-16,1,2,3]) 

771 >>> np.array2string(x, precision=2, separator=',', 

772 ... suppress_small=True) 

773 '[0.,1.,2.,3.]' 

774 

775 >>> x = np.arange(3.) 

776 >>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x}) 

777 '[0.00 1.00 2.00]' 

778 

779 >>> x = np.arange(3) 

780 >>> np.array2string(x, formatter={'int':lambda x: hex(x)}) 

781 '[0x0 0x1 0x2]' 

782 

783 """ 

784 

785 overrides = _make_options_dict(precision, threshold, edgeitems, 

786 max_line_width, suppress_small, None, None, 

787 sign, formatter, floatmode, legacy) 

788 options = format_options.get().copy() 

789 options.update(overrides) 

790 

791 if options['legacy'] <= 113: 

792 if a.shape == () and a.dtype.names is None: 

793 return repr(a.item()) 

794 

795 if options['legacy'] > 113: 

796 options['linewidth'] -= len(suffix) 

797 

798 # treat as a null array if any of shape elements == 0 

799 if a.size == 0: 

800 return "[]" 

801 

802 return _array2string(a, options, separator, prefix) 

803 

804 

805def _extendLine(s, line, word, line_width, next_line_prefix, legacy): 

806 needs_wrap = len(line) + len(word) > line_width 

807 if legacy > 113: 

808 # don't wrap lines if it won't help 

809 if len(line) <= len(next_line_prefix): 

810 needs_wrap = False 

811 

812 if needs_wrap: 

813 s += line.rstrip() + "\n" 

814 line = next_line_prefix 

815 line += word 

816 return s, line 

817 

818 

819def _extendLine_pretty(s, line, word, line_width, next_line_prefix, legacy): 

820 """ 

821 Extends line with nicely formatted (possibly multi-line) string ``word``. 

822 """ 

823 words = word.splitlines() 

824 if len(words) == 1 or legacy <= 113: 

825 return _extendLine(s, line, word, line_width, next_line_prefix, legacy) 

826 

827 max_word_length = max(len(word) for word in words) 

828 if (len(line) + max_word_length > line_width and 

829 len(line) > len(next_line_prefix)): 

830 s += line.rstrip() + '\n' 

831 line = next_line_prefix + words[0] 

832 indent = next_line_prefix 

833 else: 

834 indent = len(line) * ' ' 

835 line += words[0] 

836 

837 for word in words[1::]: 

838 s += line.rstrip() + '\n' 

839 line = indent + word 

840 

841 suffix_length = max_word_length - len(words[-1]) 

842 line += suffix_length * ' ' 

843 

844 return s, line 

845 

846def _formatArray(a, format_function, line_width, next_line_prefix, 

847 separator, edge_items, summary_insert, legacy): 

848 """formatArray is designed for two modes of operation: 

849 

850 1. Full output 

851 

852 2. Summarized output 

853 

854 """ 

855 def recurser(index, hanging_indent, curr_width): 

856 """ 

857 By using this local function, we don't need to recurse with all the 

858 arguments. Since this function is not created recursively, the cost is 

859 not significant 

860 """ 

861 axis = len(index) 

862 axes_left = a.ndim - axis 

863 

864 if axes_left == 0: 

865 return format_function(a[index]) 

866 

867 # when recursing, add a space to align with the [ added, and reduce the 

868 # length of the line by 1 

869 next_hanging_indent = hanging_indent + ' ' 

870 if legacy <= 113: 

871 next_width = curr_width 

872 else: 

873 next_width = curr_width - len(']') 

874 

875 a_len = a.shape[axis] 

876 show_summary = summary_insert and 2 * edge_items < a_len 

877 if show_summary: 

878 leading_items = edge_items 

879 trailing_items = edge_items 

880 else: 

881 leading_items = 0 

882 trailing_items = a_len 

883 

884 # stringify the array with the hanging indent on the first line too 

885 s = '' 

886 

887 # last axis (rows) - wrap elements if they would not fit on one line 

888 if axes_left == 1: 

889 # the length up until the beginning of the separator / bracket 

890 if legacy <= 113: 

891 elem_width = curr_width - len(separator.rstrip()) 

892 else: 

893 elem_width = curr_width - max( 

894 len(separator.rstrip()), len(']') 

895 ) 

896 

897 line = hanging_indent 

898 for i in range(leading_items): 

899 word = recurser(index + (i,), next_hanging_indent, next_width) 

900 s, line = _extendLine_pretty( 

901 s, line, word, elem_width, hanging_indent, legacy) 

902 line += separator 

903 

904 if show_summary: 

905 s, line = _extendLine( 

906 s, line, summary_insert, elem_width, hanging_indent, legacy 

907 ) 

908 if legacy <= 113: 

909 line += ", " 

910 else: 

911 line += separator 

912 

913 for i in range(trailing_items, 1, -1): 

914 word = recurser(index + (-i,), next_hanging_indent, next_width) 

915 s, line = _extendLine_pretty( 

916 s, line, word, elem_width, hanging_indent, legacy) 

917 line += separator 

918 

919 if legacy <= 113: 

920 # width of the separator is not considered on 1.13 

921 elem_width = curr_width 

922 word = recurser(index + (-1,), next_hanging_indent, next_width) 

923 s, line = _extendLine_pretty( 

924 s, line, word, elem_width, hanging_indent, legacy) 

925 

926 s += line 

927 

928 # other axes - insert newlines between rows 

929 else: 

930 s = '' 

931 line_sep = separator.rstrip() + '\n' * (axes_left - 1) 

932 

933 for i in range(leading_items): 

934 nested = recurser( 

935 index + (i,), next_hanging_indent, next_width 

936 ) 

937 s += hanging_indent + nested + line_sep 

938 

939 if show_summary: 

940 if legacy <= 113: 

941 # trailing space, fixed nbr of newlines, 

942 # and fixed separator 

943 s += hanging_indent + summary_insert + ", \n" 

944 else: 

945 s += hanging_indent + summary_insert + line_sep 

946 

947 for i in range(trailing_items, 1, -1): 

948 nested = recurser(index + (-i,), next_hanging_indent, 

949 next_width) 

950 s += hanging_indent + nested + line_sep 

951 

952 nested = recurser(index + (-1,), next_hanging_indent, next_width) 

953 s += hanging_indent + nested 

954 

955 # remove the hanging indent, and wrap in [] 

956 s = '[' + s[len(hanging_indent):] + ']' 

957 return s 

958 

959 try: 

960 # invoke the recursive part with an initial index and prefix 

961 return recurser(index=(), 

962 hanging_indent=next_line_prefix, 

963 curr_width=line_width) 

964 finally: 

965 # recursive closures have a cyclic reference to themselves, which 

966 # requires gc to collect (gh-10620). To avoid this problem, for 

967 # performance and PyPy friendliness, we break the cycle: 

968 recurser = None 

969 

970def _none_or_positive_arg(x, name): 

971 if x is None: 

972 return -1 

973 if x < 0: 

974 raise ValueError(f"{name} must be >= 0") 

975 return x 

976 

977class FloatingFormat: 

978 """ Formatter for subtypes of np.floating """ 

979 def __init__(self, data, precision, floatmode, suppress_small, sign=False, 

980 *, legacy=None): 

981 # for backcompatibility, accept bools 

982 if isinstance(sign, bool): 

983 sign = '+' if sign else '-' 

984 

985 self._legacy = legacy 

986 if self._legacy <= 113: 

987 # when not 0d, legacy does not support '-' 

988 if data.shape != () and sign == '-': 

989 sign = ' ' 

990 

991 self.floatmode = floatmode 

992 if floatmode == 'unique': 

993 self.precision = None 

994 else: 

995 self.precision = precision 

996 

997 self.precision = _none_or_positive_arg(self.precision, 'precision') 

998 

999 self.suppress_small = suppress_small 

1000 self.sign = sign 

1001 self.exp_format = False 

1002 self.large_exponent = False 

1003 self.fillFormat(data) 

1004 

1005 def fillFormat(self, data): 

1006 # only the finite values are used to compute the number of digits 

1007 finite_vals = data[isfinite(data)] 

1008 

1009 # choose exponential mode based on the non-zero finite values: 

1010 abs_non_zero = absolute(finite_vals[finite_vals != 0]) 

1011 if len(abs_non_zero) != 0: 

1012 max_val = np.max(abs_non_zero) 

1013 min_val = np.min(abs_non_zero) 

1014 if self._legacy <= 202: 

1015 exp_cutoff_max = 1.e8 

1016 else: 

1017 # consider data type while deciding the max cutoff for exp format 

1018 exp_cutoff_max = 10.**min(8, np.finfo(data.dtype).precision) 

1019 with errstate(over='ignore'): # division can overflow 

1020 if max_val >= exp_cutoff_max or (not self.suppress_small and 

1021 (min_val < 0.0001 or max_val / min_val > 1000.)): 

1022 self.exp_format = True 

1023 

1024 # do a first pass of printing all the numbers, to determine sizes 

1025 if len(finite_vals) == 0: 

1026 self.pad_left = 0 

1027 self.pad_right = 0 

1028 self.trim = '.' 

1029 self.exp_size = -1 

1030 self.unique = True 

1031 self.min_digits = None 

1032 elif self.exp_format: 

1033 trim, unique = '.', True 

1034 if self.floatmode == 'fixed' or self._legacy <= 113: 

1035 trim, unique = 'k', False 

1036 strs = (dragon4_scientific(x, precision=self.precision, 

1037 unique=unique, trim=trim, sign=self.sign == '+') 

1038 for x in finite_vals) 

1039 frac_strs, _, exp_strs = zip(*(s.partition('e') for s in strs)) 

1040 int_part, frac_part = zip(*(s.split('.') for s in frac_strs)) 

1041 self.exp_size = max(len(s) for s in exp_strs) - 1 

1042 

1043 self.trim = 'k' 

1044 self.precision = max(len(s) for s in frac_part) 

1045 self.min_digits = self.precision 

1046 self.unique = unique 

1047 

1048 # for back-compat with np 1.13, use 2 spaces & sign and full prec 

1049 if self._legacy <= 113: 

1050 self.pad_left = 3 

1051 else: 

1052 # this should be only 1 or 2. Can be calculated from sign. 

1053 self.pad_left = max(len(s) for s in int_part) 

1054 # pad_right is only needed for nan length calculation 

1055 self.pad_right = self.exp_size + 2 + self.precision 

1056 else: 

1057 trim, unique = '.', True 

1058 if self.floatmode == 'fixed': 

1059 trim, unique = 'k', False 

1060 strs = (dragon4_positional(x, precision=self.precision, 

1061 fractional=True, 

1062 unique=unique, trim=trim, 

1063 sign=self.sign == '+') 

1064 for x in finite_vals) 

1065 int_part, frac_part = zip(*(s.split('.') for s in strs)) 

1066 if self._legacy <= 113: 

1067 self.pad_left = 1 + max(len(s.lstrip('-+')) for s in int_part) 

1068 else: 

1069 self.pad_left = max(len(s) for s in int_part) 

1070 self.pad_right = max(len(s) for s in frac_part) 

1071 self.exp_size = -1 

1072 self.unique = unique 

1073 

1074 if self.floatmode in ['fixed', 'maxprec_equal']: 

1075 self.precision = self.min_digits = self.pad_right 

1076 self.trim = 'k' 

1077 else: 

1078 self.trim = '.' 

1079 self.min_digits = 0 

1080 

1081 if self._legacy > 113: 

1082 # account for sign = ' ' by adding one to pad_left 

1083 if self.sign == ' ' and not any(np.signbit(finite_vals)): 

1084 self.pad_left += 1 

1085 

1086 # if there are non-finite values, may need to increase pad_left 

1087 if data.size != finite_vals.size: 

1088 neginf = self.sign != '-' or any(data[isinf(data)] < 0) 

1089 offset = self.pad_right + 1 # +1 for decimal pt 

1090 current_options = format_options.get() 

1091 self.pad_left = max( 

1092 self.pad_left, len(current_options['nanstr']) - offset, 

1093 len(current_options['infstr']) + neginf - offset 

1094 ) 

1095 

1096 def __call__(self, x): 

1097 if not np.isfinite(x): 

1098 with errstate(invalid='ignore'): 

1099 current_options = format_options.get() 

1100 if np.isnan(x): 

1101 sign = '+' if self.sign == '+' else '' 

1102 ret = sign + current_options['nanstr'] 

1103 else: # isinf 

1104 sign = '-' if x < 0 else '+' if self.sign == '+' else '' 

1105 ret = sign + current_options['infstr'] 

1106 return ' ' * ( 

1107 self.pad_left + self.pad_right + 1 - len(ret) 

1108 ) + ret 

1109 

1110 if self.exp_format: 

1111 return dragon4_scientific(x, 

1112 precision=self.precision, 

1113 min_digits=self.min_digits, 

1114 unique=self.unique, 

1115 trim=self.trim, 

1116 sign=self.sign == '+', 

1117 pad_left=self.pad_left, 

1118 exp_digits=self.exp_size) 

1119 else: 

1120 return dragon4_positional(x, 

1121 precision=self.precision, 

1122 min_digits=self.min_digits, 

1123 unique=self.unique, 

1124 fractional=True, 

1125 trim=self.trim, 

1126 sign=self.sign == '+', 

1127 pad_left=self.pad_left, 

1128 pad_right=self.pad_right) 

1129 

1130 

1131@set_module('numpy') 

1132def format_float_scientific(x, precision=None, unique=True, trim='k', 

1133 sign=False, pad_left=None, exp_digits=None, 

1134 min_digits=None): 

1135 """ 

1136 Format a floating-point scalar as a decimal string in scientific notation. 

1137 

1138 Provides control over rounding, trimming and padding. Uses and assumes 

1139 IEEE unbiased rounding. Uses the "Dragon4" algorithm. 

1140 

1141 Parameters 

1142 ---------- 

1143 x : python float or numpy floating scalar 

1144 Value to format. 

1145 precision : non-negative integer or None, optional 

1146 Maximum number of digits to print. May be None if `unique` is 

1147 `True`, but must be an integer if unique is `False`. 

1148 unique : boolean, optional 

1149 If `True`, use a digit-generation strategy which gives the shortest 

1150 representation which uniquely identifies the floating-point number from 

1151 other values of the same type, by judicious rounding. If `precision` 

1152 is given fewer digits than necessary can be printed. If `min_digits` 

1153 is given more can be printed, in which cases the last digit is rounded 

1154 with unbiased rounding. 

1155 If `False`, digits are generated as if printing an infinite-precision 

1156 value and stopping after `precision` digits, rounding the remaining 

1157 value with unbiased rounding 

1158 trim : one of 'k', '.', '0', '-', optional 

1159 Controls post-processing trimming of trailing digits, as follows: 

1160 

1161 * 'k' : keep trailing zeros, keep decimal point (no trimming) 

1162 * '.' : trim all trailing zeros, leave decimal point 

1163 * '0' : trim all but the zero before the decimal point. Insert the 

1164 zero if it is missing. 

1165 * '-' : trim trailing zeros and any trailing decimal point 

1166 sign : boolean, optional 

1167 Whether to show the sign for positive values. 

1168 pad_left : non-negative integer, optional 

1169 Pad the left side of the string with whitespace until at least that 

1170 many characters are to the left of the decimal point. 

1171 exp_digits : non-negative integer, optional 

1172 Pad the exponent with zeros until it contains at least this 

1173 many digits. If omitted, the exponent will be at least 2 digits. 

1174 min_digits : non-negative integer or None, optional 

1175 Minimum number of digits to print. This only has an effect for 

1176 `unique=True`. In that case more digits than necessary to uniquely 

1177 identify the value may be printed and rounded unbiased. 

1178 

1179 .. versionadded:: 1.21.0 

1180 

1181 Returns 

1182 ------- 

1183 rep : string 

1184 The string representation of the floating point value 

1185 

1186 See Also 

1187 -------- 

1188 format_float_positional 

1189 

1190 Examples 

1191 -------- 

1192 >>> import numpy as np 

1193 >>> np.format_float_scientific(np.float32(np.pi)) 

1194 '3.1415927e+00' 

1195 >>> s = np.float32(1.23e24) 

1196 >>> np.format_float_scientific(s, unique=False, precision=15) 

1197 '1.230000071797338e+24' 

1198 >>> np.format_float_scientific(s, exp_digits=4) 

1199 '1.23e+0024' 

1200 """ 

1201 precision = _none_or_positive_arg(precision, 'precision') 

1202 pad_left = _none_or_positive_arg(pad_left, 'pad_left') 

1203 exp_digits = _none_or_positive_arg(exp_digits, 'exp_digits') 

1204 min_digits = _none_or_positive_arg(min_digits, 'min_digits') 

1205 if min_digits > 0 and precision > 0 and min_digits > precision: 

1206 raise ValueError("min_digits must be less than or equal to precision") 

1207 return dragon4_scientific(x, precision=precision, unique=unique, 

1208 trim=trim, sign=sign, pad_left=pad_left, 

1209 exp_digits=exp_digits, min_digits=min_digits) 

1210 

1211 

1212@set_module('numpy') 

1213def format_float_positional(x, precision=None, unique=True, 

1214 fractional=True, trim='k', sign=False, 

1215 pad_left=None, pad_right=None, min_digits=None): 

1216 """ 

1217 Format a floating-point scalar as a decimal string in positional notation. 

1218 

1219 Provides control over rounding, trimming and padding. Uses and assumes 

1220 IEEE unbiased rounding. Uses the "Dragon4" algorithm. 

1221 

1222 Parameters 

1223 ---------- 

1224 x : python float or numpy floating scalar 

1225 Value to format. 

1226 precision : non-negative integer or None, optional 

1227 Maximum number of digits to print. May be None if `unique` is 

1228 `True`, but must be an integer if unique is `False`. 

1229 unique : boolean, optional 

1230 If `True`, use a digit-generation strategy which gives the shortest 

1231 representation which uniquely identifies the floating-point number from 

1232 other values of the same type, by judicious rounding. If `precision` 

1233 is given fewer digits than necessary can be printed, or if `min_digits` 

1234 is given more can be printed, in which cases the last digit is rounded 

1235 with unbiased rounding. 

1236 If `False`, digits are generated as if printing an infinite-precision 

1237 value and stopping after `precision` digits, rounding the remaining 

1238 value with unbiased rounding 

1239 fractional : boolean, optional 

1240 If `True`, the cutoffs of `precision` and `min_digits` refer to the 

1241 total number of digits after the decimal point, including leading 

1242 zeros. 

1243 If `False`, `precision` and `min_digits` refer to the total number of 

1244 significant digits, before or after the decimal point, ignoring leading 

1245 zeros. 

1246 trim : one of 'k', '.', '0', '-', optional 

1247 Controls post-processing trimming of trailing digits, as follows: 

1248 

1249 * 'k' : keep trailing zeros, keep decimal point (no trimming) 

1250 * '.' : trim all trailing zeros, leave decimal point 

1251 * '0' : trim all but the zero before the decimal point. Insert the 

1252 zero if it is missing. 

1253 * '-' : trim trailing zeros and any trailing decimal point 

1254 sign : boolean, optional 

1255 Whether to show the sign for positive values. 

1256 pad_left : non-negative integer, optional 

1257 Pad the left side of the string with whitespace until at least that 

1258 many characters are to the left of the decimal point. 

1259 pad_right : non-negative integer, optional 

1260 Pad the right side of the string with whitespace until at least that 

1261 many characters are to the right of the decimal point. 

1262 min_digits : non-negative integer or None, optional 

1263 Minimum number of digits to print. Only has an effect if `unique=True` 

1264 in which case additional digits past those necessary to uniquely 

1265 identify the value may be printed, rounding the last additional digit. 

1266 

1267 .. versionadded:: 1.21.0 

1268 

1269 Returns 

1270 ------- 

1271 rep : string 

1272 The string representation of the floating point value 

1273 

1274 See Also 

1275 -------- 

1276 format_float_scientific 

1277 

1278 Examples 

1279 -------- 

1280 >>> import numpy as np 

1281 >>> np.format_float_positional(np.float32(np.pi)) 

1282 '3.1415927' 

1283 >>> np.format_float_positional(np.float16(np.pi)) 

1284 '3.14' 

1285 >>> np.format_float_positional(np.float16(0.3)) 

1286 '0.3' 

1287 >>> np.format_float_positional(np.float16(0.3), unique=False, precision=10) 

1288 '0.3000488281' 

1289 """ 

1290 precision = _none_or_positive_arg(precision, 'precision') 

1291 pad_left = _none_or_positive_arg(pad_left, 'pad_left') 

1292 pad_right = _none_or_positive_arg(pad_right, 'pad_right') 

1293 min_digits = _none_or_positive_arg(min_digits, 'min_digits') 

1294 if not fractional and precision == 0: 

1295 raise ValueError("precision must be greater than 0 if " 

1296 "fractional=False") 

1297 if min_digits > 0 and precision > 0 and min_digits > precision: 

1298 raise ValueError("min_digits must be less than or equal to precision") 

1299 return dragon4_positional(x, precision=precision, unique=unique, 

1300 fractional=fractional, trim=trim, 

1301 sign=sign, pad_left=pad_left, 

1302 pad_right=pad_right, min_digits=min_digits) 

1303 

1304class IntegerFormat: 

1305 def __init__(self, data, sign='-'): 

1306 if data.size > 0: 

1307 data_max = np.max(data) 

1308 data_min = np.min(data) 

1309 data_max_str_len = len(str(data_max)) 

1310 if sign == ' ' and data_min < 0: 

1311 sign = '-' 

1312 if data_max >= 0 and sign in "+ ": 

1313 data_max_str_len += 1 

1314 max_str_len = max(data_max_str_len, 

1315 len(str(data_min))) 

1316 else: 

1317 max_str_len = 0 

1318 self.format = f'{{:{sign}{max_str_len}d}}' 

1319 

1320 def __call__(self, x): 

1321 return self.format.format(x) 

1322 

1323class BoolFormat: 

1324 def __init__(self, data, **kwargs): 

1325 # add an extra space so " True" and "False" have the same length and 

1326 # array elements align nicely when printed, except in 0d arrays 

1327 self.truestr = ' True' if data.shape != () else 'True' 

1328 

1329 def __call__(self, x): 

1330 return self.truestr if x else "False" 

1331 

1332 

1333class ComplexFloatingFormat: 

1334 """ Formatter for subtypes of np.complexfloating """ 

1335 def __init__(self, x, precision, floatmode, suppress_small, 

1336 sign=False, *, legacy=None): 

1337 # for backcompatibility, accept bools 

1338 if isinstance(sign, bool): 

1339 sign = '+' if sign else '-' 

1340 

1341 floatmode_real = floatmode_imag = floatmode 

1342 if legacy <= 113: 

1343 floatmode_real = 'maxprec_equal' 

1344 floatmode_imag = 'maxprec' 

1345 

1346 self.real_format = FloatingFormat( 

1347 x.real, precision, floatmode_real, suppress_small, 

1348 sign=sign, legacy=legacy 

1349 ) 

1350 self.imag_format = FloatingFormat( 

1351 x.imag, precision, floatmode_imag, suppress_small, 

1352 sign='+', legacy=legacy 

1353 ) 

1354 

1355 def __call__(self, x): 

1356 r = self.real_format(x.real) 

1357 i = self.imag_format(x.imag) 

1358 

1359 # add the 'j' before the terminal whitespace in i 

1360 sp = len(i.rstrip()) 

1361 i = i[:sp] + 'j' + i[sp:] 

1362 

1363 return r + i 

1364 

1365 

1366class _TimelikeFormat: 

1367 def __init__(self, data): 

1368 non_nat = data[~isnat(data)] 

1369 if len(non_nat) > 0: 

1370 # Max str length of non-NaT elements 

1371 max_str_len = max(len(self._format_non_nat(np.max(non_nat))), 

1372 len(self._format_non_nat(np.min(non_nat)))) 

1373 else: 

1374 max_str_len = 0 

1375 if len(non_nat) < data.size: 

1376 # data contains a NaT 

1377 max_str_len = max(max_str_len, 5) 

1378 self._format = f'%{max_str_len}s' 

1379 self._nat = "'NaT'".rjust(max_str_len) 

1380 

1381 def _format_non_nat(self, x): 

1382 # override in subclass 

1383 raise NotImplementedError 

1384 

1385 def __call__(self, x): 

1386 if isnat(x): 

1387 return self._nat 

1388 else: 

1389 return self._format % self._format_non_nat(x) 

1390 

1391 

1392class DatetimeFormat(_TimelikeFormat): 

1393 def __init__(self, x, unit=None, timezone=None, casting='same_kind', 

1394 legacy=False): 

1395 # Get the unit from the dtype 

1396 if unit is None: 

1397 if x.dtype.kind == 'M': 

1398 unit = datetime_data(x.dtype)[0] 

1399 else: 

1400 unit = 's' 

1401 

1402 if timezone is None: 

1403 timezone = 'naive' 

1404 self.timezone = timezone 

1405 self.unit = unit 

1406 self.casting = casting 

1407 self.legacy = legacy 

1408 

1409 # must be called after the above are configured 

1410 super().__init__(x) 

1411 

1412 def __call__(self, x): 

1413 if self.legacy <= 113: 

1414 return self._format_non_nat(x) 

1415 return super().__call__(x) 

1416 

1417 def _format_non_nat(self, x): 

1418 return "'%s'" % datetime_as_string(x, 

1419 unit=self.unit, 

1420 timezone=self.timezone, 

1421 casting=self.casting) 

1422 

1423 

1424class TimedeltaFormat(_TimelikeFormat): 

1425 def _format_non_nat(self, x): 

1426 return str(x.astype('i8')) 

1427 

1428 

1429class SubArrayFormat: 

1430 def __init__(self, format_function, **options): 

1431 self.format_function = format_function 

1432 self.threshold = options['threshold'] 

1433 self.edge_items = options['edgeitems'] 

1434 

1435 def __call__(self, a): 

1436 self.summary_insert = "..." if a.size > self.threshold else "" 

1437 return self.format_array(a) 

1438 

1439 def format_array(self, a): 

1440 if np.ndim(a) == 0: 

1441 return self.format_function(a) 

1442 

1443 if self.summary_insert and a.shape[0] > 2 * self.edge_items: 

1444 formatted = ( 

1445 [self.format_array(a_) for a_ in a[:self.edge_items]] 

1446 + [self.summary_insert] 

1447 + [self.format_array(a_) for a_ in a[-self.edge_items:]] 

1448 ) 

1449 else: 

1450 formatted = [self.format_array(a_) for a_ in a] 

1451 

1452 return "[" + ", ".join(formatted) + "]" 

1453 

1454 

1455class StructuredVoidFormat: 

1456 """ 

1457 Formatter for structured np.void objects. 

1458 

1459 This does not work on structured alias types like 

1460 np.dtype(('i4', 'i2,i2')), as alias scalars lose their field information, 

1461 and the implementation relies upon np.void.__getitem__. 

1462 """ 

1463 def __init__(self, format_functions): 

1464 self.format_functions = format_functions 

1465 

1466 @classmethod 

1467 def from_data(cls, data, **options): 

1468 """ 

1469 This is a second way to initialize StructuredVoidFormat, 

1470 using the raw data as input. Added to avoid changing 

1471 the signature of __init__. 

1472 """ 

1473 format_functions = [] 

1474 for field_name in data.dtype.names: 

1475 format_function = _get_format_function(data[field_name], **options) 

1476 if data.dtype[field_name].shape != (): 

1477 format_function = SubArrayFormat(format_function, **options) 

1478 format_functions.append(format_function) 

1479 return cls(format_functions) 

1480 

1481 def __call__(self, x): 

1482 str_fields = [ 

1483 format_function(field) 

1484 for field, format_function in zip(x, self.format_functions) 

1485 ] 

1486 if len(str_fields) == 1: 

1487 return f"({str_fields[0]},)" 

1488 else: 

1489 return f"({', '.join(str_fields)})" 

1490 

1491 

1492def _void_scalar_to_string(x, is_repr=True): 

1493 """ 

1494 Implements the repr for structured-void scalars. It is called from the 

1495 scalartypes.c.src code, and is placed here because it uses the elementwise 

1496 formatters defined above. 

1497 """ 

1498 options = format_options.get().copy() 

1499 

1500 if options["legacy"] <= 125: 

1501 return StructuredVoidFormat.from_data(array(x), **options)(x) 

1502 

1503 if options.get('formatter') is None: 

1504 options['formatter'] = {} 

1505 options['formatter'].setdefault('float_kind', str) 

1506 val_repr = StructuredVoidFormat.from_data(array(x), **options)(x) 

1507 if not is_repr: 

1508 return val_repr 

1509 cls = type(x) 

1510 cls_fqn = cls.__module__.replace("numpy", "np") + "." + cls.__name__ 

1511 void_dtype = np.dtype((np.void, x.dtype)) 

1512 return f"{cls_fqn}({val_repr}, dtype={void_dtype!s})" 

1513 

1514 

1515_typelessdata = [int_, float64, complex128, _nt.bool] 

1516 

1517 

1518def dtype_is_implied(dtype): 

1519 """ 

1520 Determine if the given dtype is implied by the representation 

1521 of its values. 

1522 

1523 Parameters 

1524 ---------- 

1525 dtype : dtype 

1526 Data type 

1527 

1528 Returns 

1529 ------- 

1530 implied : bool 

1531 True if the dtype is implied by the representation of its values. 

1532 

1533 Examples 

1534 -------- 

1535 >>> import numpy as np 

1536 >>> np._core.arrayprint.dtype_is_implied(int) 

1537 True 

1538 >>> np.array([1, 2, 3], int) 

1539 array([1, 2, 3]) 

1540 >>> np._core.arrayprint.dtype_is_implied(np.int8) 

1541 False 

1542 >>> np.array([1, 2, 3], np.int8) 

1543 array([1, 2, 3], dtype=int8) 

1544 """ 

1545 dtype = np.dtype(dtype) 

1546 if format_options.get()['legacy'] <= 113 and dtype.type == np.bool: 

1547 return False 

1548 

1549 # not just void types can be structured, and names are not part of the repr 

1550 if dtype.names is not None: 

1551 return False 

1552 

1553 # should care about endianness *unless size is 1* (e.g., int8, bool) 

1554 if not dtype.isnative: 

1555 return False 

1556 

1557 return dtype.type in _typelessdata 

1558 

1559 

1560def dtype_short_repr(dtype): 

1561 """ 

1562 Convert a dtype to a short form which evaluates to the same dtype. 

1563 

1564 The intent is roughly that the following holds 

1565 

1566 >>> from numpy import * 

1567 >>> dt = np.int64([1, 2]).dtype 

1568 >>> assert eval(dtype_short_repr(dt)) == dt 

1569 """ 

1570 if type(dtype).__repr__ != np.dtype.__repr__: 

1571 # TODO: Custom repr for user DTypes, logic should likely move. 

1572 return repr(dtype) 

1573 if dtype.names is not None: 

1574 # structured dtypes give a list or tuple repr 

1575 return str(dtype) 

1576 elif issubclass(dtype.type, flexible): 

1577 # handle these separately so they don't give garbage like str256 

1578 return f"'{str(dtype)}'" 

1579 

1580 typename = dtype.name 

1581 if not dtype.isnative: 

1582 # deal with cases like dtype('<u2') that are identical to an 

1583 # established dtype (in this case uint16) 

1584 # except that they have a different endianness. 

1585 return f"'{str(dtype)}'" 

1586 # quote typenames which can't be represented as python variable names 

1587 if typename and not (typename[0].isalpha() and typename.isalnum()): 

1588 typename = repr(typename) 

1589 return typename 

1590 

1591 

1592def _array_repr_implementation( 

1593 arr, max_line_width=None, precision=None, suppress_small=None, 

1594 array2string=array2string): 

1595 """Internal version of array_repr() that allows overriding array2string.""" 

1596 current_options = format_options.get() 

1597 override_repr = current_options["override_repr"] 

1598 if override_repr is not None: 

1599 return override_repr(arr) 

1600 

1601 if max_line_width is None: 

1602 max_line_width = current_options['linewidth'] 

1603 

1604 if type(arr) is not ndarray: 

1605 class_name = type(arr).__name__ 

1606 else: 

1607 class_name = "array" 

1608 

1609 prefix = class_name + "(" 

1610 if (current_options['legacy'] <= 113 and 

1611 arr.shape == () and not arr.dtype.names): 

1612 lst = repr(arr.item()) 

1613 else: 

1614 lst = array2string(arr, max_line_width, precision, suppress_small, 

1615 ', ', prefix, suffix=")") 

1616 

1617 # Add dtype and shape information if these cannot be inferred from 

1618 # the array string. 

1619 extras = [] 

1620 if ((arr.size == 0 and arr.shape != (0,)) 

1621 or (current_options['legacy'] > 210 

1622 and arr.size > current_options['threshold'])): 

1623 extras.append(f"shape={arr.shape}") 

1624 if not dtype_is_implied(arr.dtype) or arr.size == 0: 

1625 extras.append(f"dtype={dtype_short_repr(arr.dtype)}") 

1626 

1627 if not extras: 

1628 return prefix + lst + ")" 

1629 

1630 arr_str = prefix + lst + "," 

1631 extra_str = ", ".join(extras) + ")" 

1632 # compute whether we should put extras on a new line: Do so if adding the 

1633 # extras would extend the last line past max_line_width. 

1634 # Note: This line gives the correct result even when rfind returns -1. 

1635 last_line_len = len(arr_str) - (arr_str.rfind('\n') + 1) 

1636 spacer = " " 

1637 if current_options['legacy'] <= 113: 

1638 if issubclass(arr.dtype.type, flexible): 

1639 spacer = '\n' + ' ' * len(prefix) 

1640 elif last_line_len + len(extra_str) + 1 > max_line_width: 

1641 spacer = '\n' + ' ' * len(prefix) 

1642 

1643 return arr_str + spacer + extra_str 

1644 

1645 

1646def _array_repr_dispatcher( 

1647 arr, max_line_width=None, precision=None, suppress_small=None): 

1648 return (arr,) 

1649 

1650 

1651@array_function_dispatch(_array_repr_dispatcher, module='numpy') 

1652def array_repr(arr, max_line_width=None, precision=None, suppress_small=None): 

1653 """ 

1654 Return the string representation of an array. 

1655 

1656 Parameters 

1657 ---------- 

1658 arr : ndarray 

1659 Input array. 

1660 max_line_width : int, optional 

1661 Inserts newlines if text is longer than `max_line_width`. 

1662 Defaults to ``numpy.get_printoptions()['linewidth']``. 

1663 precision : int, optional 

1664 Floating point precision. 

1665 Defaults to ``numpy.get_printoptions()['precision']``. 

1666 suppress_small : bool, optional 

1667 Represent numbers "very close" to zero as zero; default is False. 

1668 Very close is defined by precision: if the precision is 8, e.g., 

1669 numbers smaller (in absolute value) than 5e-9 are represented as 

1670 zero. 

1671 Defaults to ``numpy.get_printoptions()['suppress']``. 

1672 

1673 Returns 

1674 ------- 

1675 string : str 

1676 The string representation of an array. 

1677 

1678 See Also 

1679 -------- 

1680 array_str, array2string, set_printoptions 

1681 

1682 Examples 

1683 -------- 

1684 >>> import numpy as np 

1685 >>> np.array_repr(np.array([1,2])) 

1686 'array([1, 2])' 

1687 >>> np.array_repr(np.ma.array([0.])) 

1688 'MaskedArray([0.])' 

1689 >>> np.array_repr(np.array([], np.int32)) 

1690 'array([], dtype=int32)' 

1691 

1692 >>> x = np.array([1e-6, 4e-7, 2, 3]) 

1693 >>> np.array_repr(x, precision=6, suppress_small=True) 

1694 'array([0.000001, 0. , 2. , 3. ])' 

1695 

1696 """ 

1697 return _array_repr_implementation( 

1698 arr, max_line_width, precision, suppress_small) 

1699 

1700 

1701@_recursive_guard() 

1702def _guarded_repr_or_str(v): 

1703 if isinstance(v, bytes): 

1704 return repr(v) 

1705 return str(v) 

1706 

1707 

1708def _array_str_implementation( 

1709 a, max_line_width=None, precision=None, suppress_small=None, 

1710 array2string=array2string): 

1711 """Internal version of array_str() that allows overriding array2string.""" 

1712 if (format_options.get()['legacy'] <= 113 and 

1713 a.shape == () and not a.dtype.names): 

1714 return str(a.item()) 

1715 

1716 # the str of 0d arrays is a special case: It should appear like a scalar, 

1717 # so floats are not truncated by `precision`, and strings are not wrapped 

1718 # in quotes. So we return the str of the scalar value. 

1719 if a.shape == (): 

1720 # obtain a scalar and call str on it, avoiding problems for subclasses 

1721 # for which indexing with () returns a 0d instead of a scalar by using 

1722 # ndarray's getindex. Also guard against recursive 0d object arrays. 

1723 return _guarded_repr_or_str(np.ndarray.__getitem__(a, ())) 

1724 

1725 return array2string(a, max_line_width, precision, suppress_small, ' ', "") 

1726 

1727 

1728def _array_str_dispatcher( 

1729 a, max_line_width=None, precision=None, suppress_small=None): 

1730 return (a,) 

1731 

1732 

1733@array_function_dispatch(_array_str_dispatcher, module='numpy') 

1734def array_str(a, max_line_width=None, precision=None, suppress_small=None): 

1735 """ 

1736 Return a string representation of the data in an array. 

1737 

1738 The data in the array is returned as a single string. This function is 

1739 similar to `array_repr`, the difference being that `array_repr` also 

1740 returns information on the kind of array and its data type. 

1741 

1742 Parameters 

1743 ---------- 

1744 a : ndarray 

1745 Input array. 

1746 max_line_width : int, optional 

1747 Inserts newlines if text is longer than `max_line_width`. 

1748 Defaults to ``numpy.get_printoptions()['linewidth']``. 

1749 precision : int, optional 

1750 Floating point precision. 

1751 Defaults to ``numpy.get_printoptions()['precision']``. 

1752 suppress_small : bool, optional 

1753 Represent numbers "very close" to zero as zero; default is False. 

1754 Very close is defined by precision: if the precision is 8, e.g., 

1755 numbers smaller (in absolute value) than 5e-9 are represented as 

1756 zero. 

1757 Defaults to ``numpy.get_printoptions()['suppress']``. 

1758 

1759 See Also 

1760 -------- 

1761 array2string, array_repr, set_printoptions 

1762 

1763 Examples 

1764 -------- 

1765 >>> import numpy as np 

1766 >>> np.array_str(np.arange(3)) 

1767 '[0 1 2]' 

1768 

1769 """ 

1770 return _array_str_implementation( 

1771 a, max_line_width, precision, suppress_small) 

1772 

1773 

1774# needed if __array_function__ is disabled 

1775_array2string_impl = getattr(array2string, '__wrapped__', array2string) 

1776_default_array_str = functools.partial(_array_str_implementation, 

1777 array2string=_array2string_impl) 

1778_default_array_repr = functools.partial(_array_repr_implementation, 

1779 array2string=_array2string_impl)