Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/_core/arrayprint.py: 19%

604 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-09 06:12 +0000

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, 

39 set_legacy_print_mode) 

40from .fromnumeric import any 

41from .numeric import concatenate, asarray, errstate 

42from .numerictypes import (longlong, intc, int_, float64, complex128, 

43 flexible) 

44from .overrides import array_function_dispatch, set_module 

45import operator 

46import warnings 

47import contextlib 

48 

49_format_options = { 

50 'edgeitems': 3, # repr N leading and trailing items of each dimension 

51 'threshold': 1000, # total items > triggers array summarization 

52 'floatmode': 'maxprec', 

53 'precision': 8, # precision of floating point representations 

54 'suppress': False, # suppress printing small floating values in exp format 

55 'linewidth': 75, 

56 'nanstr': 'nan', 

57 'infstr': 'inf', 

58 'sign': '-', 

59 'formatter': None, 

60 # Internally stored as an int to simplify comparisons; converted from/to 

61 # str/False on the way in/out. 

62 'legacy': sys.maxsize} 

63 

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

65 linewidth=None, suppress=None, nanstr=None, infstr=None, 

66 sign=None, formatter=None, floatmode=None, legacy=None): 

67 """ 

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

69 *legacy* and sanity checks. 

70 """ 

71 

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

73 

74 if suppress is not None: 

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

76 

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

78 if floatmode not in modes + [None]: 

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

80 ", ".join('"{}"'.format(m) for m in modes)) 

81 

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

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

84 

85 if legacy == False: 

86 options['legacy'] = sys.maxsize 

87 elif legacy == '1.13': 

88 options['legacy'] = 113 

89 elif legacy == '1.21': 

90 options['legacy'] = 121 

91 elif legacy == '1.25': 

92 options['legacy'] = 125 

93 elif legacy is None: 

94 pass # OK, do nothing. 

95 else: 

96 warnings.warn( 

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

98 "'1.25', or `False`", stacklevel=3) 

99 

100 if threshold is not None: 

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

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

103 raise TypeError("threshold must be numeric") 

104 if np.isnan(threshold): 

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

106 "sys.maxsize for untruncated representation") 

107 

108 if precision is not None: 

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

110 try: 

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

112 except TypeError as e: 

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

114 

115 return options 

116 

117 

118@set_module('numpy') 

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

120 linewidth=None, suppress=None, nanstr=None, 

121 infstr=None, formatter=None, sign=None, floatmode=None, 

122 *, legacy=None): 

123 """ 

124 Set printing options. 

125 

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

127 other NumPy objects are displayed. 

128 

129 Parameters 

130 ---------- 

131 precision : int or None, optional 

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

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

134 necessary to uniquely specify the value. 

135 threshold : int, optional 

136 Total number of array elements which trigger summarization 

137 rather than full repr (default 1000). 

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

139 edgeitems : int, optional 

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

141 each dimension (default 3). 

142 linewidth : int, optional 

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

144 line breaks (default 75). 

145 suppress : bool, optional 

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

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

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

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

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

151 nanstr : str, optional 

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

153 infstr : str, optional 

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

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

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

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

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

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

160 

161 .. versionchanged:: 2.0 

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

163 types were floating-point types. 

164 

165 formatter : dict of callables, optional 

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

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

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

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

170 can be set are: 

171 

172 - 'bool' 

173 - 'int' 

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

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

176 - 'float' 

177 - 'longfloat' : 128-bit floats 

178 - 'complexfloat' 

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

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

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

182 

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

184 

185 - 'all' : sets all types 

186 - 'int_kind' : sets 'int' 

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

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

189 - 'str_kind' : sets 'numpystr' 

190 floatmode : str, optional 

191 Controls the interpretation of the `precision` option for 

192 floating-point types. Can take the following values 

193 (default maxprec_equal): 

194 

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

196 even if this would print more or fewer digits than 

197 necessary to specify the value uniquely. 

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

199 to represent each value uniquely. Different elements may 

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

201 `precision` option is ignored. 

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

203 an element can be uniquely represented with fewer digits 

204 only print it with that many. 

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

206 but if every element in the array can be uniquely 

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

208 many digits for all elements. 

209 legacy : string or `False`, optional 

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

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

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

213 enables 1.21 legacy printing mode (described below). 

214 

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

216 approximates numpy 1.21 print output of complex structured dtypes 

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

218 colons. 

219 

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

221 

222 Unrecognized strings will be ignored with a warning for forward 

223 compatibility. 

224 

225 .. versionadded:: 1.14.0 

226 .. versionchanged:: 1.22.0 

227 

228 See Also 

229 -------- 

230 get_printoptions, printoptions, array2string 

231 

232 Notes 

233 ----- 

234 `formatter` is always reset with a call to `set_printoptions`. 

235 

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

237 

238 Examples 

239 -------- 

240 Floating point precision can be set: 

241 

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

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

244 [1.1235] 

245 

246 Long arrays can be summarised: 

247 

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

249 >>> np.arange(10) 

250 array([0, 1, 2, ..., 7, 8, 9]) 

251 

252 Small results can be suppressed: 

253 

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

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

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

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

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

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

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

261 

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

263 

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

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

266 >>> x 

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

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

269 >>> x 

270 array([0, 1, 2]) 

271 

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

273 

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

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

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

277 

278 Also to temporarily override options, use `printoptions` 

279 as a context manager: 

280 

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

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

283 array([ 0. , 1.11, 2.22, ..., 7.78, 8.89, 10. ]) 

284 

285 """ 

286 opt = _make_options_dict(precision, threshold, edgeitems, linewidth, 

287 suppress, nanstr, infstr, sign, formatter, 

288 floatmode, legacy) 

289 # formatter is always reset 

290 opt['formatter'] = formatter 

291 _format_options.update(opt) 

292 

293 # set the C variable for legacy mode 

294 if _format_options['legacy'] == 113: 

295 set_legacy_print_mode(113) 

296 # reset the sign option in legacy mode to avoid confusion 

297 _format_options['sign'] = '-' 

298 elif _format_options['legacy'] == 121: 

299 set_legacy_print_mode(121) 

300 elif _format_options['legacy'] == 125: 

301 set_legacy_print_mode(125) 

302 elif _format_options['legacy'] == sys.maxsize: 

303 set_legacy_print_mode(0) 

304 

305 

306@set_module('numpy') 

307def get_printoptions(): 

308 """ 

309 Return the current print options. 

310 

311 Returns 

312 ------- 

313 print_opts : dict 

314 Dictionary of current print options with keys 

315 

316 - precision : int 

317 - threshold : int 

318 - edgeitems : int 

319 - linewidth : int 

320 - suppress : bool 

321 - nanstr : str 

322 - infstr : str 

323 - formatter : dict of callables 

324 - sign : str 

325 

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

327 

328 See Also 

329 -------- 

330 set_printoptions, printoptions 

331 

332 """ 

333 opts = _format_options.copy() 

334 opts['legacy'] = { 

335 113: '1.13', 121: '1.21', 125: '1.25', sys.maxsize: False, 

336 }[opts['legacy']] 

337 return opts 

338 

339 

340def _get_legacy_print_mode(): 

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

342 return _format_options['legacy'] 

343 

344 

345@set_module('numpy') 

346@contextlib.contextmanager 

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

348 """Context manager for setting print options. 

349 

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

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

352 available options. 

353 

354 Examples 

355 -------- 

356 

357 >>> from numpy.testing import assert_equal 

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

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

360 array([0.67]) 

361 

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

363 

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

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

366 

367 See Also 

368 -------- 

369 set_printoptions, get_printoptions 

370 

371 """ 

372 opts = np.get_printoptions() 

373 try: 

374 np.set_printoptions(*args, **kwargs) 

375 yield np.get_printoptions() 

376 finally: 

377 np.set_printoptions(**opts) 

378 

379 

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

381 """ 

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

383 

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

385 preserving subclasses. 

386 """ 

387 axis = len(index) 

388 if axis == a.ndim: 

389 return a[index] 

390 

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

392 return concatenate(( 

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

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

395 ), axis=axis) 

396 else: 

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

398 

399 

400def _object_format(o): 

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

402 if type(o) is list: 

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

404 else: 

405 fmt = '{!r}' 

406 return fmt.format(o) 

407 

408def repr_format(x): 

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

410 return repr(x.item()) 

411 return repr(x) 

412 

413def str_format(x): 

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

415 return str(x.item()) 

416 return str(x) 

417 

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

419 formatter, **kwargs): 

420 # note: extra arguments in kwargs are ignored 

421 

422 # wrapped in lambdas to avoid taking a code path 

423 # with the wrong type of data 

424 formatdict = { 

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

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

427 'float': lambda: FloatingFormat( 

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

429 'longfloat': lambda: FloatingFormat( 

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

431 'complexfloat': lambda: ComplexFloatingFormat( 

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

433 'longcomplexfloat': lambda: ComplexFloatingFormat( 

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

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

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

437 'object': lambda: _object_format, 

438 'void': lambda: str_format, 

439 'numpystr': lambda: repr_format} 

440 

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

442 # is the same as the above values. 

443 def indirect(x): 

444 return lambda: x 

445 

446 if formatter is not None: 

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

448 if 'all' in fkeys: 

449 for key in formatdict.keys(): 

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

451 if 'int_kind' in fkeys: 

452 for key in ['int']: 

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

454 if 'float_kind' in fkeys: 

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

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

457 if 'complex_kind' in fkeys: 

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

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

460 if 'str_kind' in fkeys: 

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

462 for key in formatdict.keys(): 

463 if key in fkeys: 

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

465 

466 return formatdict 

467 

468def _get_format_function(data, **options): 

469 """ 

470 find the right formatting function for the dtype_ 

471 """ 

472 dtype_ = data.dtype 

473 dtypeobj = dtype_.type 

474 formatdict = _get_formatdict(data, **options) 

475 if dtypeobj is None: 

476 return formatdict["numpystr"]() 

477 elif issubclass(dtypeobj, _nt.bool): 

478 return formatdict['bool']() 

479 elif issubclass(dtypeobj, _nt.integer): 

480 if issubclass(dtypeobj, _nt.timedelta64): 

481 return formatdict['timedelta']() 

482 else: 

483 return formatdict['int']() 

484 elif issubclass(dtypeobj, _nt.floating): 

485 if issubclass(dtypeobj, _nt.longdouble): 

486 return formatdict['longfloat']() 

487 else: 

488 return formatdict['float']() 

489 elif issubclass(dtypeobj, _nt.complexfloating): 

490 if issubclass(dtypeobj, _nt.clongdouble): 

491 return formatdict['longcomplexfloat']() 

492 else: 

493 return formatdict['complexfloat']() 

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

495 return formatdict['numpystr']() 

496 elif issubclass(dtypeobj, _nt.datetime64): 

497 return formatdict['datetime']() 

498 elif issubclass(dtypeobj, _nt.object_): 

499 return formatdict['object']() 

500 elif issubclass(dtypeobj, _nt.void): 

501 if dtype_.names is not None: 

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

503 else: 

504 return formatdict['void']() 

505 else: 

506 return formatdict['numpystr']() 

507 

508 

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

510 """ 

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

512 

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

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

515 

516 Largely copied from reprlib.recursive_repr 

517 """ 

518 

519 def decorating_function(f): 

520 repr_running = set() 

521 

522 @functools.wraps(f) 

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

524 key = id(self), get_ident() 

525 if key in repr_running: 

526 return fillvalue 

527 repr_running.add(key) 

528 try: 

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

530 finally: 

531 repr_running.discard(key) 

532 

533 return wrapper 

534 

535 return decorating_function 

536 

537 

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

539@_recursive_guard() 

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

541 # The formatter __init__s in _get_format_function cannot deal with 

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

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

544 data = asarray(a) 

545 if a.shape == (): 

546 a = data 

547 

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

549 summary_insert = "..." 

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

551 else: 

552 summary_insert = "" 

553 

554 # find the right formatting function for the array 

555 format_function = _get_format_function(data, **options) 

556 

557 # skip over "[" 

558 next_line_prefix = " " 

559 # skip over array( 

560 next_line_prefix += " "*len(prefix) 

561 

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

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

564 summary_insert, options['legacy']) 

565 return lst 

566 

567 

568def _array2string_dispatcher( 

569 a, max_line_width=None, precision=None, 

570 suppress_small=None, separator=None, prefix=None, 

571 style=None, formatter=None, threshold=None, 

572 edgeitems=None, sign=None, floatmode=None, suffix=None, 

573 *, legacy=None): 

574 return (a,) 

575 

576 

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

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

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

580 style=np._NoValue, formatter=None, threshold=None, 

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

582 *, legacy=None): 

583 """ 

584 Return a string representation of an array. 

585 

586 Parameters 

587 ---------- 

588 a : ndarray 

589 Input array. 

590 max_line_width : int, optional 

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

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

593 precision : int or None, optional 

594 Floating point precision. 

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

596 suppress_small : bool, optional 

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

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

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

600 zero. 

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

602 separator : str, optional 

603 Inserted between elements. 

604 prefix : str, optional 

605 suffix : str, optional 

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

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

608 

609 prefix + array2string(a) + suffix 

610 

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

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

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

614 not included in the output. 

615 style : _NoValue, optional 

616 Has no effect, do not use. 

617 

618 .. deprecated:: 1.14.0 

619 formatter : dict of callables, optional 

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

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

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

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

624 can be set are: 

625 

626 - 'bool' 

627 - 'int' 

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

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

630 - 'float' 

631 - 'longfloat' : 128-bit floats 

632 - 'complexfloat' 

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

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

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

636 

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

638 

639 - 'all' : sets all types 

640 - 'int_kind' : sets 'int' 

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

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

643 - 'str_kind' : sets 'numpystr' 

644 threshold : int, optional 

645 Total number of array elements which trigger summarization 

646 rather than full repr. 

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

648 edgeitems : int, optional 

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

650 each dimension. 

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

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

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

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

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

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

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

658 

659 .. versionchanged:: 2.0 

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

661 types were floating-point types. 

662 

663 floatmode : str, optional 

664 Controls the interpretation of the `precision` option for 

665 floating-point types. 

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

667 Can take the following values: 

668 

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

670 even if this would print more or fewer digits than 

671 necessary to specify the value uniquely. 

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

673 to represent each value uniquely. Different elements may 

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

675 `precision` option is ignored. 

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

677 an element can be uniquely represented with fewer digits 

678 only print it with that many. 

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

680 but if every element in the array can be uniquely 

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

682 many digits for all elements. 

683 legacy : string or `False`, optional 

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

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

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

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

688 with a warning for forward compatibility. 

689 

690 .. versionadded:: 1.14.0 

691 

692 Returns 

693 ------- 

694 array_str : str 

695 String representation of the array. 

696 

697 Raises 

698 ------ 

699 TypeError 

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

701 

702 See Also 

703 -------- 

704 array_str, array_repr, set_printoptions, get_printoptions 

705 

706 Notes 

707 ----- 

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

709 ignored for that type. 

710 

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

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

713 identically in all three functions. 

714 

715 Examples 

716 -------- 

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

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

719 ... suppress_small=True) 

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

721 

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

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

724 '[0.00 1.00 2.00]' 

725 

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

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

728 '[0x0 0x1 0x2]' 

729 

730 """ 

731 

732 overrides = _make_options_dict(precision, threshold, edgeitems, 

733 max_line_width, suppress_small, None, None, 

734 sign, formatter, floatmode, legacy) 

735 options = _format_options.copy() 

736 options.update(overrides) 

737 

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

739 if style is np._NoValue: 

740 style = repr 

741 

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

743 return style(a.item()) 

744 elif style is not np._NoValue: 

745 # Deprecation 11-9-2017 v1.14 

746 warnings.warn("'style' argument is deprecated and no longer functional" 

747 " except in 1.13 'legacy' mode", 

748 DeprecationWarning, stacklevel=2) 

749 

750 if options['legacy'] > 113: 

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

752 

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

754 if a.size == 0: 

755 return "[]" 

756 

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

758 

759 

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

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

762 if legacy > 113: 

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

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

765 needs_wrap = False 

766 

767 if needs_wrap: 

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

769 line = next_line_prefix 

770 line += word 

771 return s, line 

772 

773 

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

775 """ 

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

777 """ 

778 words = word.splitlines() 

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

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

781 

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

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

784 len(line) > len(next_line_prefix)): 

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

786 line = next_line_prefix + words[0] 

787 indent = next_line_prefix 

788 else: 

789 indent = len(line)*' ' 

790 line += words[0] 

791 

792 for word in words[1::]: 

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

794 line = indent + word 

795 

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

797 line += suffix_length*' ' 

798 

799 return s, line 

800 

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

802 separator, edge_items, summary_insert, legacy): 

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

804 

805 1. Full output 

806 

807 2. Summarized output 

808 

809 """ 

810 def recurser(index, hanging_indent, curr_width): 

811 """ 

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

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

814 not significant 

815 """ 

816 axis = len(index) 

817 axes_left = a.ndim - axis 

818 

819 if axes_left == 0: 

820 return format_function(a[index]) 

821 

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

823 # length of the line by 1 

824 next_hanging_indent = hanging_indent + ' ' 

825 if legacy <= 113: 

826 next_width = curr_width 

827 else: 

828 next_width = curr_width - len(']') 

829 

830 a_len = a.shape[axis] 

831 show_summary = summary_insert and 2*edge_items < a_len 

832 if show_summary: 

833 leading_items = edge_items 

834 trailing_items = edge_items 

835 else: 

836 leading_items = 0 

837 trailing_items = a_len 

838 

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

840 s = '' 

841 

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

843 if axes_left == 1: 

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

845 if legacy <= 113: 

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

847 else: 

848 elem_width = curr_width - max( 

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

850 ) 

851 

852 line = hanging_indent 

853 for i in range(leading_items): 

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

855 s, line = _extendLine_pretty( 

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

857 line += separator 

858 

859 if show_summary: 

860 s, line = _extendLine( 

861 s, line, summary_insert, elem_width, hanging_indent, legacy 

862 ) 

863 if legacy <= 113: 

864 line += ", " 

865 else: 

866 line += separator 

867 

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

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

870 s, line = _extendLine_pretty( 

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

872 line += separator 

873 

874 if legacy <= 113: 

875 # width of the separator is not considered on 1.13 

876 elem_width = curr_width 

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

878 s, line = _extendLine_pretty( 

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

880 

881 s += line 

882 

883 # other axes - insert newlines between rows 

884 else: 

885 s = '' 

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

887 

888 for i in range(leading_items): 

889 nested = recurser( 

890 index + (i,), next_hanging_indent, next_width 

891 ) 

892 s += hanging_indent + nested + line_sep 

893 

894 if show_summary: 

895 if legacy <= 113: 

896 # trailing space, fixed nbr of newlines, 

897 # and fixed separator 

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

899 else: 

900 s += hanging_indent + summary_insert + line_sep 

901 

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

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

904 next_width) 

905 s += hanging_indent + nested + line_sep 

906 

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

908 s += hanging_indent + nested 

909 

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

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

912 return s 

913 

914 try: 

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

916 return recurser(index=(), 

917 hanging_indent=next_line_prefix, 

918 curr_width=line_width) 

919 finally: 

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

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

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

923 recurser = None 

924 

925def _none_or_positive_arg(x, name): 

926 if x is None: 

927 return -1 

928 if x < 0: 

929 raise ValueError("{} must be >= 0".format(name)) 

930 return x 

931 

932class FloatingFormat: 

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

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

935 *, legacy=None): 

936 # for backcompatibility, accept bools 

937 if isinstance(sign, bool): 

938 sign = '+' if sign else '-' 

939 

940 self._legacy = legacy 

941 if self._legacy <= 113: 

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

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

944 sign = ' ' 

945 

946 self.floatmode = floatmode 

947 if floatmode == 'unique': 

948 self.precision = None 

949 else: 

950 self.precision = precision 

951 

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

953 

954 self.suppress_small = suppress_small 

955 self.sign = sign 

956 self.exp_format = False 

957 self.large_exponent = False 

958 

959 self.fillFormat(data) 

960 

961 def fillFormat(self, data): 

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

963 finite_vals = data[isfinite(data)] 

964 

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

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

967 if len(abs_non_zero) != 0: 

968 max_val = np.max(abs_non_zero) 

969 min_val = np.min(abs_non_zero) 

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

971 if max_val >= 1.e8 or (not self.suppress_small and 

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

973 self.exp_format = True 

974 

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

976 if len(finite_vals) == 0: 

977 self.pad_left = 0 

978 self.pad_right = 0 

979 self.trim = '.' 

980 self.exp_size = -1 

981 self.unique = True 

982 self.min_digits = None 

983 elif self.exp_format: 

984 trim, unique = '.', True 

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

986 trim, unique = 'k', False 

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

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

989 for x in finite_vals) 

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

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

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

993 

994 self.trim = 'k' 

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

996 self.min_digits = self.precision 

997 self.unique = unique 

998 

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

1000 if self._legacy <= 113: 

1001 self.pad_left = 3 

1002 else: 

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

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

1005 # pad_right is only needed for nan length calculation 

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

1007 else: 

1008 trim, unique = '.', True 

1009 if self.floatmode == 'fixed': 

1010 trim, unique = 'k', False 

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

1012 fractional=True, 

1013 unique=unique, trim=trim, 

1014 sign=self.sign == '+') 

1015 for x in finite_vals) 

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

1017 if self._legacy <= 113: 

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

1019 else: 

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

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

1022 self.exp_size = -1 

1023 self.unique = unique 

1024 

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

1026 self.precision = self.min_digits = self.pad_right 

1027 self.trim = 'k' 

1028 else: 

1029 self.trim = '.' 

1030 self.min_digits = 0 

1031 

1032 if self._legacy > 113: 

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

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

1035 self.pad_left += 1 

1036 

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

1038 if data.size != finite_vals.size: 

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

1040 nanlen = len(_format_options['nanstr']) 

1041 inflen = len(_format_options['infstr']) + neginf 

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

1043 self.pad_left = max( 

1044 self.pad_left, nanlen - offset, inflen - offset 

1045 ) 

1046 

1047 def __call__(self, x): 

1048 if not np.isfinite(x): 

1049 with errstate(invalid='ignore'): 

1050 if np.isnan(x): 

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

1052 ret = sign + _format_options['nanstr'] 

1053 else: # isinf 

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

1055 ret = sign + _format_options['infstr'] 

1056 return ' '*( 

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

1058 ) + ret 

1059 

1060 if self.exp_format: 

1061 return dragon4_scientific(x, 

1062 precision=self.precision, 

1063 min_digits=self.min_digits, 

1064 unique=self.unique, 

1065 trim=self.trim, 

1066 sign=self.sign == '+', 

1067 pad_left=self.pad_left, 

1068 exp_digits=self.exp_size) 

1069 else: 

1070 return dragon4_positional(x, 

1071 precision=self.precision, 

1072 min_digits=self.min_digits, 

1073 unique=self.unique, 

1074 fractional=True, 

1075 trim=self.trim, 

1076 sign=self.sign == '+', 

1077 pad_left=self.pad_left, 

1078 pad_right=self.pad_right) 

1079 

1080 

1081@set_module('numpy') 

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

1083 sign=False, pad_left=None, exp_digits=None, 

1084 min_digits=None): 

1085 """ 

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

1087 

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

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

1090 

1091 Parameters 

1092 ---------- 

1093 x : python float or numpy floating scalar 

1094 Value to format. 

1095 precision : non-negative integer or None, optional 

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

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

1098 unique : boolean, optional 

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

1100 representation which uniquely identifies the floating-point number from 

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

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

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

1104 with unbiased rounding. 

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

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

1107 value with unbiased rounding 

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

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

1110 

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

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

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

1114 zero if it is missing. 

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

1116 sign : boolean, optional 

1117 Whether to show the sign for positive values. 

1118 pad_left : non-negative integer, optional 

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

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

1121 exp_digits : non-negative integer, optional 

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

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

1124 min_digits : non-negative integer or None, optional 

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

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

1127 identify the value may be printed and rounded unbiased. 

1128 

1129 .. versionadded:: 1.21.0 

1130 

1131 Returns 

1132 ------- 

1133 rep : string 

1134 The string representation of the floating point value 

1135 

1136 See Also 

1137 -------- 

1138 format_float_positional 

1139 

1140 Examples 

1141 -------- 

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

1143 '3.1415927e+00' 

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

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

1146 '1.230000071797338e+24' 

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

1148 '1.23e+0024' 

1149 """ 

1150 precision = _none_or_positive_arg(precision, 'precision') 

1151 pad_left = _none_or_positive_arg(pad_left, 'pad_left') 

1152 exp_digits = _none_or_positive_arg(exp_digits, 'exp_digits') 

1153 min_digits = _none_or_positive_arg(min_digits, 'min_digits') 

1154 if min_digits > 0 and precision > 0 and min_digits > precision: 

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

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

1157 trim=trim, sign=sign, pad_left=pad_left, 

1158 exp_digits=exp_digits, min_digits=min_digits) 

1159 

1160 

1161@set_module('numpy') 

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

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

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

1165 """ 

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

1167 

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

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

1170 

1171 Parameters 

1172 ---------- 

1173 x : python float or numpy floating scalar 

1174 Value to format. 

1175 precision : non-negative integer or None, optional 

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

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

1178 unique : boolean, optional 

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

1180 representation which uniquely identifies the floating-point number from 

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

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

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

1184 with unbiased rounding. 

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

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

1187 value with unbiased rounding 

1188 fractional : boolean, optional 

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

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

1191 zeros. 

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

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

1194 zeros. 

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

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

1197 

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

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

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

1201 zero if it is missing. 

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

1203 sign : boolean, optional 

1204 Whether to show the sign for positive values. 

1205 pad_left : non-negative integer, optional 

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

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

1208 pad_right : non-negative integer, optional 

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

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

1211 min_digits : non-negative integer or None, optional 

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

1213 in which case additional digits past those necessary to uniquely 

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

1215 

1216 .. versionadded:: 1.21.0 

1217 

1218 Returns 

1219 ------- 

1220 rep : string 

1221 The string representation of the floating point value 

1222 

1223 See Also 

1224 -------- 

1225 format_float_scientific 

1226 

1227 Examples 

1228 -------- 

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

1230 '3.1415927' 

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

1232 '3.14' 

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

1234 '0.3' 

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

1236 '0.3000488281' 

1237 """ 

1238 precision = _none_or_positive_arg(precision, 'precision') 

1239 pad_left = _none_or_positive_arg(pad_left, 'pad_left') 

1240 pad_right = _none_or_positive_arg(pad_right, 'pad_right') 

1241 min_digits = _none_or_positive_arg(min_digits, 'min_digits') 

1242 if not fractional and precision == 0: 

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

1244 "fractional=False") 

1245 if min_digits > 0 and precision > 0 and min_digits > precision: 

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

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

1248 fractional=fractional, trim=trim, 

1249 sign=sign, pad_left=pad_left, 

1250 pad_right=pad_right, min_digits=min_digits) 

1251 

1252class IntegerFormat: 

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

1254 if data.size > 0: 

1255 data_max = np.max(data) 

1256 data_min = np.min(data) 

1257 data_max_str_len = len(str(data_max)) 

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

1259 sign = '-' 

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

1261 data_max_str_len += 1 

1262 max_str_len = max(data_max_str_len, 

1263 len(str(data_min))) 

1264 else: 

1265 max_str_len = 0 

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

1267 

1268 def __call__(self, x): 

1269 return self.format.format(x) 

1270 

1271class BoolFormat: 

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

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

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

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

1276 

1277 def __call__(self, x): 

1278 return self.truestr if x else "False" 

1279 

1280 

1281class ComplexFloatingFormat: 

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

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

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

1285 # for backcompatibility, accept bools 

1286 if isinstance(sign, bool): 

1287 sign = '+' if sign else '-' 

1288 

1289 floatmode_real = floatmode_imag = floatmode 

1290 if legacy <= 113: 

1291 floatmode_real = 'maxprec_equal' 

1292 floatmode_imag = 'maxprec' 

1293 

1294 self.real_format = FloatingFormat( 

1295 x.real, precision, floatmode_real, suppress_small, 

1296 sign=sign, legacy=legacy 

1297 ) 

1298 self.imag_format = FloatingFormat( 

1299 x.imag, precision, floatmode_imag, suppress_small, 

1300 sign='+', legacy=legacy 

1301 ) 

1302 

1303 def __call__(self, x): 

1304 r = self.real_format(x.real) 

1305 i = self.imag_format(x.imag) 

1306 

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

1308 sp = len(i.rstrip()) 

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

1310 

1311 return r + i 

1312 

1313 

1314class _TimelikeFormat: 

1315 def __init__(self, data): 

1316 non_nat = data[~isnat(data)] 

1317 if len(non_nat) > 0: 

1318 # Max str length of non-NaT elements 

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

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

1321 else: 

1322 max_str_len = 0 

1323 if len(non_nat) < data.size: 

1324 # data contains a NaT 

1325 max_str_len = max(max_str_len, 5) 

1326 self._format = '%{}s'.format(max_str_len) 

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

1328 

1329 def _format_non_nat(self, x): 

1330 # override in subclass 

1331 raise NotImplementedError 

1332 

1333 def __call__(self, x): 

1334 if isnat(x): 

1335 return self._nat 

1336 else: 

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

1338 

1339 

1340class DatetimeFormat(_TimelikeFormat): 

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

1342 legacy=False): 

1343 # Get the unit from the dtype 

1344 if unit is None: 

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

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

1347 else: 

1348 unit = 's' 

1349 

1350 if timezone is None: 

1351 timezone = 'naive' 

1352 self.timezone = timezone 

1353 self.unit = unit 

1354 self.casting = casting 

1355 self.legacy = legacy 

1356 

1357 # must be called after the above are configured 

1358 super().__init__(x) 

1359 

1360 def __call__(self, x): 

1361 if self.legacy <= 113: 

1362 return self._format_non_nat(x) 

1363 return super().__call__(x) 

1364 

1365 def _format_non_nat(self, x): 

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

1367 unit=self.unit, 

1368 timezone=self.timezone, 

1369 casting=self.casting) 

1370 

1371 

1372class TimedeltaFormat(_TimelikeFormat): 

1373 def _format_non_nat(self, x): 

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

1375 

1376 

1377class SubArrayFormat: 

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

1379 self.format_function = format_function 

1380 self.threshold = options['threshold'] 

1381 self.edge_items = options['edgeitems'] 

1382 

1383 def __call__(self, a): 

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

1385 return self.format_array(a) 

1386 

1387 def format_array(self, a): 

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

1389 return self.format_function(a) 

1390 

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

1392 formatted = ( 

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

1394 + [self.summary_insert] 

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

1396 ) 

1397 else: 

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

1399 

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

1401 

1402 

1403class StructuredVoidFormat: 

1404 """ 

1405 Formatter for structured np.void objects. 

1406 

1407 This does not work on structured alias types like 

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

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

1410 """ 

1411 def __init__(self, format_functions): 

1412 self.format_functions = format_functions 

1413 

1414 @classmethod 

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

1416 """ 

1417 This is a second way to initialize StructuredVoidFormat, 

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

1419 the signature of __init__. 

1420 """ 

1421 format_functions = [] 

1422 for field_name in data.dtype.names: 

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

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

1425 format_function = SubArrayFormat(format_function, **options) 

1426 format_functions.append(format_function) 

1427 return cls(format_functions) 

1428 

1429 def __call__(self, x): 

1430 str_fields = [ 

1431 format_function(field) 

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

1433 ] 

1434 if len(str_fields) == 1: 

1435 return "({},)".format(str_fields[0]) 

1436 else: 

1437 return "({})".format(", ".join(str_fields)) 

1438 

1439 

1440def _void_scalar_to_string(x, is_repr=True): 

1441 """ 

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

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

1444 formatters defined above. 

1445 """ 

1446 options = _format_options.copy() 

1447 

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

1449 return StructuredVoidFormat.from_data(array(x), **_format_options)(x) 

1450 

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

1452 options['formatter'] = {} 

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

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

1455 if not is_repr: 

1456 return val_repr 

1457 cls = type(x) 

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

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

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

1461 

1462 

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

1464 

1465 

1466def dtype_is_implied(dtype): 

1467 """ 

1468 Determine if the given dtype is implied by the representation 

1469 of its values. 

1470 

1471 Parameters 

1472 ---------- 

1473 dtype : dtype 

1474 Data type 

1475 

1476 Returns 

1477 ------- 

1478 implied : bool 

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

1480 

1481 Examples 

1482 -------- 

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

1484 True 

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

1486 array([1, 2, 3]) 

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

1488 False 

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

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

1491 """ 

1492 dtype = np.dtype(dtype) 

1493 if _format_options['legacy'] <= 113 and dtype.type == np.bool: 

1494 return False 

1495 

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

1497 if dtype.names is not None: 

1498 return False 

1499 

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

1501 if not dtype.isnative: 

1502 return False 

1503 

1504 return dtype.type in _typelessdata 

1505 

1506 

1507def dtype_short_repr(dtype): 

1508 """ 

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

1510 

1511 The intent is roughly that the following holds 

1512 

1513 >>> from numpy import * 

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

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

1516 """ 

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

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

1519 return repr(dtype) 

1520 if dtype.names is not None: 

1521 # structured dtypes give a list or tuple repr 

1522 return str(dtype) 

1523 elif issubclass(dtype.type, flexible): 

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

1525 return "'%s'" % str(dtype) 

1526 

1527 typename = dtype.name 

1528 if not dtype.isnative: 

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

1530 # established dtype (in this case uint16) 

1531 # except that they have a different endianness. 

1532 return "'%s'" % str(dtype) 

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

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

1535 typename = repr(typename) 

1536 return typename 

1537 

1538 

1539def _array_repr_implementation( 

1540 arr, max_line_width=None, precision=None, suppress_small=None, 

1541 array2string=array2string): 

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

1543 if max_line_width is None: 

1544 max_line_width = _format_options['linewidth'] 

1545 

1546 if type(arr) is not ndarray: 

1547 class_name = type(arr).__name__ 

1548 else: 

1549 class_name = "array" 

1550 

1551 skipdtype = dtype_is_implied(arr.dtype) and arr.size > 0 

1552 

1553 prefix = class_name + "(" 

1554 suffix = ")" if skipdtype else "," 

1555 

1556 if (_format_options['legacy'] <= 113 and 

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

1558 lst = repr(arr.item()) 

1559 elif arr.size > 0 or arr.shape == (0,): 

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

1561 ', ', prefix, suffix=suffix) 

1562 else: # show zero-length shape unless it is (0,) 

1563 lst = "[], shape=%s" % (repr(arr.shape),) 

1564 

1565 arr_str = prefix + lst + suffix 

1566 

1567 if skipdtype: 

1568 return arr_str 

1569 

1570 dtype_str = "dtype={})".format(dtype_short_repr(arr.dtype)) 

1571 

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

1573 # dtype would extend the last line past max_line_width. 

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

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

1576 spacer = " " 

1577 if _format_options['legacy'] <= 113: 

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

1579 spacer = '\n' + ' '*len(class_name + "(") 

1580 elif last_line_len + len(dtype_str) + 1 > max_line_width: 

1581 spacer = '\n' + ' '*len(class_name + "(") 

1582 

1583 return arr_str + spacer + dtype_str 

1584 

1585 

1586def _array_repr_dispatcher( 

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

1588 return (arr,) 

1589 

1590 

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

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

1593 """ 

1594 Return the string representation of an array. 

1595 

1596 Parameters 

1597 ---------- 

1598 arr : ndarray 

1599 Input array. 

1600 max_line_width : int, optional 

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

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

1603 precision : int, optional 

1604 Floating point precision. 

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

1606 suppress_small : bool, optional 

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

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

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

1610 zero. 

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

1612 

1613 Returns 

1614 ------- 

1615 string : str 

1616 The string representation of an array. 

1617 

1618 See Also 

1619 -------- 

1620 array_str, array2string, set_printoptions 

1621 

1622 Examples 

1623 -------- 

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

1625 'array([1, 2])' 

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

1627 'MaskedArray([0.])' 

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

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

1630 

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

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

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

1634 

1635 """ 

1636 return _array_repr_implementation( 

1637 arr, max_line_width, precision, suppress_small) 

1638 

1639 

1640@_recursive_guard() 

1641def _guarded_repr_or_str(v): 

1642 if isinstance(v, bytes): 

1643 return repr(v) 

1644 return str(v) 

1645 

1646 

1647def _array_str_implementation( 

1648 a, max_line_width=None, precision=None, suppress_small=None, 

1649 array2string=array2string): 

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

1651 if (_format_options['legacy'] <= 113 and 

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

1653 return str(a.item()) 

1654 

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

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

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

1658 if a.shape == (): 

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

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

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

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

1663 

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

1665 

1666 

1667def _array_str_dispatcher( 

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

1669 return (a,) 

1670 

1671 

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

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

1674 """ 

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

1676 

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

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

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

1680 

1681 Parameters 

1682 ---------- 

1683 a : ndarray 

1684 Input array. 

1685 max_line_width : int, optional 

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

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

1688 precision : int, optional 

1689 Floating point precision. 

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

1691 suppress_small : bool, optional 

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

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

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

1695 zero. 

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

1697 

1698 See Also 

1699 -------- 

1700 array2string, array_repr, set_printoptions 

1701 

1702 Examples 

1703 -------- 

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

1705 '[0 1 2]' 

1706 

1707 """ 

1708 return _array_str_implementation( 

1709 a, max_line_width, precision, suppress_small) 

1710 

1711 

1712# needed if __array_function__ is disabled 

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

1714_default_array_str = functools.partial(_array_str_implementation, 

1715 array2string=_array2string_impl) 

1716_default_array_repr = functools.partial(_array_repr_implementation, 

1717 array2string=_array2string_impl) 

1718 

1719 

1720def set_string_function(f, repr=True): 

1721 """ 

1722 Set a Python function to be used when pretty printing arrays. 

1723 

1724 .. deprecated:: 2.0 

1725 Use `np.set_printoptions` instead with a formatter for custom 

1726 printing of NumPy objects. 

1727 

1728 Parameters 

1729 ---------- 

1730 f : function or None 

1731 Function to be used to pretty print arrays. The function should expect 

1732 a single array argument and return a string of the representation of 

1733 the array. If None, the function is reset to the default NumPy function 

1734 to print arrays. 

1735 repr : bool, optional 

1736 If True (default), the function for pretty printing (``__repr__``) 

1737 is set, if False the function that returns the default string 

1738 representation (``__str__``) is set. 

1739 

1740 See Also 

1741 -------- 

1742 set_printoptions, get_printoptions 

1743 

1744 Examples 

1745 -------- 

1746 >>> from numpy._core.arrayprint import set_string_function 

1747 >>> def pprint(arr): 

1748 ... return 'HA! - What are you going to do now?' 

1749 ... 

1750 >>> set_string_function(pprint) 

1751 >>> a = np.arange(10) 

1752 >>> a 

1753 HA! - What are you going to do now? 

1754 >>> _ = a 

1755 >>> # [0 1 2 3 4 5 6 7 8 9] 

1756 

1757 We can reset the function to the default: 

1758 

1759 >>> set_string_function(None) 

1760 >>> a 

1761 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) 

1762 

1763 `repr` affects either pretty printing or normal string representation. 

1764 Note that ``__repr__`` is still affected by setting ``__str__`` 

1765 because the width of each array element in the returned string becomes 

1766 equal to the length of the result of ``__str__()``. 

1767 

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

1769 >>> set_string_function(lambda x:'random', repr=False) 

1770 >>> x.__str__() 

1771 'random' 

1772 >>> x.__repr__() 

1773 'array([0, 1, 2, 3])' 

1774 

1775 """ 

1776 

1777 # Deprecated in NumPy 2.0, 2023-07-11 

1778 warnings.warn( 

1779 "`set_string_function` is deprecated. Use `np.set_printoptions` " 

1780 "with a formatter for custom printing NumPy objects. " 

1781 "(deprecated in NumPy 2.0)", 

1782 DeprecationWarning, 

1783 stacklevel=2 

1784 ) 

1785 

1786 if f is None: 

1787 if repr: 

1788 return multiarray.set_string_function(_default_array_repr, 1) 

1789 else: 

1790 return multiarray.set_string_function(_default_array_str, 0) 

1791 else: 

1792 return multiarray.set_string_function(f, repr)