Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Lib/collections/__init__.py
12 views
1
'''This module implements specialized container datatypes providing
2
alternatives to Python's general purpose built-in containers, dict,
3
list, set, and tuple.
4
5
* namedtuple factory function for creating tuple subclasses with named fields
6
* deque list-like container with fast appends and pops on either end
7
* ChainMap dict-like class for creating a single view of multiple mappings
8
* Counter dict subclass for counting hashable objects
9
* OrderedDict dict subclass that remembers the order entries were added
10
* defaultdict dict subclass that calls a factory function to supply missing values
11
* UserDict wrapper around dictionary objects for easier dict subclassing
12
* UserList wrapper around list objects for easier list subclassing
13
* UserString wrapper around string objects for easier string subclassing
14
15
'''
16
17
__all__ = [
18
'ChainMap',
19
'Counter',
20
'OrderedDict',
21
'UserDict',
22
'UserList',
23
'UserString',
24
'defaultdict',
25
'deque',
26
'namedtuple',
27
]
28
29
import _collections_abc
30
import sys as _sys
31
32
from itertools import chain as _chain
33
from itertools import repeat as _repeat
34
from itertools import starmap as _starmap
35
from keyword import iskeyword as _iskeyword
36
from operator import eq as _eq
37
from operator import itemgetter as _itemgetter
38
from reprlib import recursive_repr as _recursive_repr
39
from _weakref import proxy as _proxy
40
41
try:
42
from _collections import deque
43
except ImportError:
44
pass
45
else:
46
_collections_abc.MutableSequence.register(deque)
47
48
try:
49
from _collections import _deque_iterator
50
except ImportError:
51
pass
52
53
try:
54
from _collections import defaultdict
55
except ImportError:
56
pass
57
58
59
################################################################################
60
### OrderedDict
61
################################################################################
62
63
class _OrderedDictKeysView(_collections_abc.KeysView):
64
65
def __reversed__(self):
66
yield from reversed(self._mapping)
67
68
class _OrderedDictItemsView(_collections_abc.ItemsView):
69
70
def __reversed__(self):
71
for key in reversed(self._mapping):
72
yield (key, self._mapping[key])
73
74
class _OrderedDictValuesView(_collections_abc.ValuesView):
75
76
def __reversed__(self):
77
for key in reversed(self._mapping):
78
yield self._mapping[key]
79
80
class _Link(object):
81
__slots__ = 'prev', 'next', 'key', '__weakref__'
82
83
class OrderedDict(dict):
84
'Dictionary that remembers insertion order'
85
# An inherited dict maps keys to values.
86
# The inherited dict provides __getitem__, __len__, __contains__, and get.
87
# The remaining methods are order-aware.
88
# Big-O running times for all methods are the same as regular dictionaries.
89
90
# The internal self.__map dict maps keys to links in a doubly linked list.
91
# The circular doubly linked list starts and ends with a sentinel element.
92
# The sentinel element never gets deleted (this simplifies the algorithm).
93
# The sentinel is in self.__hardroot with a weakref proxy in self.__root.
94
# The prev links are weakref proxies (to prevent circular references).
95
# Individual links are kept alive by the hard reference in self.__map.
96
# Those hard references disappear when a key is deleted from an OrderedDict.
97
98
def __init__(self, other=(), /, **kwds):
99
'''Initialize an ordered dictionary. The signature is the same as
100
regular dictionaries. Keyword argument order is preserved.
101
'''
102
try:
103
self.__root
104
except AttributeError:
105
self.__hardroot = _Link()
106
self.__root = root = _proxy(self.__hardroot)
107
root.prev = root.next = root
108
self.__map = {}
109
self.__update(other, **kwds)
110
111
def __setitem__(self, key, value,
112
dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
113
'od.__setitem__(i, y) <==> od[i]=y'
114
# Setting a new item creates a new link at the end of the linked list,
115
# and the inherited dictionary is updated with the new key/value pair.
116
if key not in self:
117
self.__map[key] = link = Link()
118
root = self.__root
119
last = root.prev
120
link.prev, link.next, link.key = last, root, key
121
last.next = link
122
root.prev = proxy(link)
123
dict_setitem(self, key, value)
124
125
def __delitem__(self, key, dict_delitem=dict.__delitem__):
126
'od.__delitem__(y) <==> del od[y]'
127
# Deleting an existing item uses self.__map to find the link which gets
128
# removed by updating the links in the predecessor and successor nodes.
129
dict_delitem(self, key)
130
link = self.__map.pop(key)
131
link_prev = link.prev
132
link_next = link.next
133
link_prev.next = link_next
134
link_next.prev = link_prev
135
link.prev = None
136
link.next = None
137
138
def __iter__(self):
139
'od.__iter__() <==> iter(od)'
140
# Traverse the linked list in order.
141
root = self.__root
142
curr = root.next
143
while curr is not root:
144
yield curr.key
145
curr = curr.next
146
147
def __reversed__(self):
148
'od.__reversed__() <==> reversed(od)'
149
# Traverse the linked list in reverse order.
150
root = self.__root
151
curr = root.prev
152
while curr is not root:
153
yield curr.key
154
curr = curr.prev
155
156
def clear(self):
157
'od.clear() -> None. Remove all items from od.'
158
root = self.__root
159
root.prev = root.next = root
160
self.__map.clear()
161
dict.clear(self)
162
163
def popitem(self, last=True):
164
'''Remove and return a (key, value) pair from the dictionary.
165
166
Pairs are returned in LIFO order if last is true or FIFO order if false.
167
'''
168
if not self:
169
raise KeyError('dictionary is empty')
170
root = self.__root
171
if last:
172
link = root.prev
173
link_prev = link.prev
174
link_prev.next = root
175
root.prev = link_prev
176
else:
177
link = root.next
178
link_next = link.next
179
root.next = link_next
180
link_next.prev = root
181
key = link.key
182
del self.__map[key]
183
value = dict.pop(self, key)
184
return key, value
185
186
def move_to_end(self, key, last=True):
187
'''Move an existing element to the end (or beginning if last is false).
188
189
Raise KeyError if the element does not exist.
190
'''
191
link = self.__map[key]
192
link_prev = link.prev
193
link_next = link.next
194
soft_link = link_next.prev
195
link_prev.next = link_next
196
link_next.prev = link_prev
197
root = self.__root
198
if last:
199
last = root.prev
200
link.prev = last
201
link.next = root
202
root.prev = soft_link
203
last.next = link
204
else:
205
first = root.next
206
link.prev = root
207
link.next = first
208
first.prev = soft_link
209
root.next = link
210
211
def __sizeof__(self):
212
sizeof = _sys.getsizeof
213
n = len(self) + 1 # number of links including root
214
size = sizeof(self.__dict__) # instance dictionary
215
size += sizeof(self.__map) * 2 # internal dict and inherited dict
216
size += sizeof(self.__hardroot) * n # link objects
217
size += sizeof(self.__root) * n # proxy objects
218
return size
219
220
update = __update = _collections_abc.MutableMapping.update
221
222
def keys(self):
223
"D.keys() -> a set-like object providing a view on D's keys"
224
return _OrderedDictKeysView(self)
225
226
def items(self):
227
"D.items() -> a set-like object providing a view on D's items"
228
return _OrderedDictItemsView(self)
229
230
def values(self):
231
"D.values() -> an object providing a view on D's values"
232
return _OrderedDictValuesView(self)
233
234
__ne__ = _collections_abc.MutableMapping.__ne__
235
236
__marker = object()
237
238
def pop(self, key, default=__marker):
239
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding
240
value. If key is not found, d is returned if given, otherwise KeyError
241
is raised.
242
243
'''
244
marker = self.__marker
245
result = dict.pop(self, key, marker)
246
if result is not marker:
247
# The same as in __delitem__().
248
link = self.__map.pop(key)
249
link_prev = link.prev
250
link_next = link.next
251
link_prev.next = link_next
252
link_next.prev = link_prev
253
link.prev = None
254
link.next = None
255
return result
256
if default is marker:
257
raise KeyError(key)
258
return default
259
260
def setdefault(self, key, default=None):
261
'''Insert key with a value of default if key is not in the dictionary.
262
263
Return the value for key if key is in the dictionary, else default.
264
'''
265
if key in self:
266
return self[key]
267
self[key] = default
268
return default
269
270
@_recursive_repr()
271
def __repr__(self):
272
'od.__repr__() <==> repr(od)'
273
if not self:
274
return '%s()' % (self.__class__.__name__,)
275
return '%s(%r)' % (self.__class__.__name__, dict(self.items()))
276
277
def __reduce__(self):
278
'Return state information for pickling'
279
state = self.__getstate__()
280
if state:
281
if isinstance(state, tuple):
282
state, slots = state
283
else:
284
slots = {}
285
state = state.copy()
286
slots = slots.copy()
287
for k in vars(OrderedDict()):
288
state.pop(k, None)
289
slots.pop(k, None)
290
if slots:
291
state = state, slots
292
else:
293
state = state or None
294
return self.__class__, (), state, None, iter(self.items())
295
296
def copy(self):
297
'od.copy() -> a shallow copy of od'
298
return self.__class__(self)
299
300
@classmethod
301
def fromkeys(cls, iterable, value=None):
302
'''Create a new ordered dictionary with keys from iterable and values set to value.
303
'''
304
self = cls()
305
for key in iterable:
306
self[key] = value
307
return self
308
309
def __eq__(self, other):
310
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
311
while comparison to a regular mapping is order-insensitive.
312
313
'''
314
if isinstance(other, OrderedDict):
315
return dict.__eq__(self, other) and all(map(_eq, self, other))
316
return dict.__eq__(self, other)
317
318
def __ior__(self, other):
319
self.update(other)
320
return self
321
322
def __or__(self, other):
323
if not isinstance(other, dict):
324
return NotImplemented
325
new = self.__class__(self)
326
new.update(other)
327
return new
328
329
def __ror__(self, other):
330
if not isinstance(other, dict):
331
return NotImplemented
332
new = self.__class__(other)
333
new.update(self)
334
return new
335
336
337
try:
338
from _collections import OrderedDict
339
except ImportError:
340
# Leave the pure Python version in place.
341
pass
342
343
344
################################################################################
345
### namedtuple
346
################################################################################
347
348
try:
349
from _collections import _tuplegetter
350
except ImportError:
351
_tuplegetter = lambda index, doc: property(_itemgetter(index), doc=doc)
352
353
def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None):
354
"""Returns a new subclass of tuple with named fields.
355
356
>>> Point = namedtuple('Point', ['x', 'y'])
357
>>> Point.__doc__ # docstring for the new class
358
'Point(x, y)'
359
>>> p = Point(11, y=22) # instantiate with positional args or keywords
360
>>> p[0] + p[1] # indexable like a plain tuple
361
33
362
>>> x, y = p # unpack like a regular tuple
363
>>> x, y
364
(11, 22)
365
>>> p.x + p.y # fields also accessible by name
366
33
367
>>> d = p._asdict() # convert to a dictionary
368
>>> d['x']
369
11
370
>>> Point(**d) # convert from a dictionary
371
Point(x=11, y=22)
372
>>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
373
Point(x=100, y=22)
374
375
"""
376
377
# Validate the field names. At the user's option, either generate an error
378
# message or automatically replace the field name with a valid name.
379
if isinstance(field_names, str):
380
field_names = field_names.replace(',', ' ').split()
381
field_names = list(map(str, field_names))
382
typename = _sys.intern(str(typename))
383
384
if rename:
385
seen = set()
386
for index, name in enumerate(field_names):
387
if (not name.isidentifier()
388
or _iskeyword(name)
389
or name.startswith('_')
390
or name in seen):
391
field_names[index] = f'_{index}'
392
seen.add(name)
393
394
for name in [typename] + field_names:
395
if type(name) is not str:
396
raise TypeError('Type names and field names must be strings')
397
if not name.isidentifier():
398
raise ValueError('Type names and field names must be valid '
399
f'identifiers: {name!r}')
400
if _iskeyword(name):
401
raise ValueError('Type names and field names cannot be a '
402
f'keyword: {name!r}')
403
404
seen = set()
405
for name in field_names:
406
if name.startswith('_') and not rename:
407
raise ValueError('Field names cannot start with an underscore: '
408
f'{name!r}')
409
if name in seen:
410
raise ValueError(f'Encountered duplicate field name: {name!r}')
411
seen.add(name)
412
413
field_defaults = {}
414
if defaults is not None:
415
defaults = tuple(defaults)
416
if len(defaults) > len(field_names):
417
raise TypeError('Got more default values than field names')
418
field_defaults = dict(reversed(list(zip(reversed(field_names),
419
reversed(defaults)))))
420
421
# Variables used in the methods and docstrings
422
field_names = tuple(map(_sys.intern, field_names))
423
num_fields = len(field_names)
424
arg_list = ', '.join(field_names)
425
if num_fields == 1:
426
arg_list += ','
427
repr_fmt = '(' + ', '.join(f'{name}=%r' for name in field_names) + ')'
428
tuple_new = tuple.__new__
429
_dict, _tuple, _len, _map, _zip = dict, tuple, len, map, zip
430
431
# Create all the named tuple methods to be added to the class namespace
432
433
namespace = {
434
'_tuple_new': tuple_new,
435
'__builtins__': {},
436
'__name__': f'namedtuple_{typename}',
437
}
438
code = f'lambda _cls, {arg_list}: _tuple_new(_cls, ({arg_list}))'
439
__new__ = eval(code, namespace)
440
__new__.__name__ = '__new__'
441
__new__.__doc__ = f'Create new instance of {typename}({arg_list})'
442
if defaults is not None:
443
__new__.__defaults__ = defaults
444
445
@classmethod
446
def _make(cls, iterable):
447
result = tuple_new(cls, iterable)
448
if _len(result) != num_fields:
449
raise TypeError(f'Expected {num_fields} arguments, got {len(result)}')
450
return result
451
452
_make.__func__.__doc__ = (f'Make a new {typename} object from a sequence '
453
'or iterable')
454
455
def _replace(self, /, **kwds):
456
result = self._make(_map(kwds.pop, field_names, self))
457
if kwds:
458
raise ValueError(f'Got unexpected field names: {list(kwds)!r}')
459
return result
460
461
_replace.__doc__ = (f'Return a new {typename} object replacing specified '
462
'fields with new values')
463
464
def __repr__(self):
465
'Return a nicely formatted representation string'
466
return self.__class__.__name__ + repr_fmt % self
467
468
def _asdict(self):
469
'Return a new dict which maps field names to their values.'
470
return _dict(_zip(self._fields, self))
471
472
def __getnewargs__(self):
473
'Return self as a plain tuple. Used by copy and pickle.'
474
return _tuple(self)
475
476
# Modify function metadata to help with introspection and debugging
477
for method in (
478
__new__,
479
_make.__func__,
480
_replace,
481
__repr__,
482
_asdict,
483
__getnewargs__,
484
):
485
method.__qualname__ = f'{typename}.{method.__name__}'
486
487
# Build-up the class namespace dictionary
488
# and use type() to build the result class
489
class_namespace = {
490
'__doc__': f'{typename}({arg_list})',
491
'__slots__': (),
492
'_fields': field_names,
493
'_field_defaults': field_defaults,
494
'__new__': __new__,
495
'_make': _make,
496
'_replace': _replace,
497
'__repr__': __repr__,
498
'_asdict': _asdict,
499
'__getnewargs__': __getnewargs__,
500
'__match_args__': field_names,
501
}
502
for index, name in enumerate(field_names):
503
doc = _sys.intern(f'Alias for field number {index}')
504
class_namespace[name] = _tuplegetter(index, doc)
505
506
result = type(typename, (tuple,), class_namespace)
507
508
# For pickling to work, the __module__ variable needs to be set to the frame
509
# where the named tuple is created. Bypass this step in environments where
510
# sys._getframe is not defined (Jython for example) or sys._getframe is not
511
# defined for arguments greater than 0 (IronPython), or where the user has
512
# specified a particular module.
513
if module is None:
514
try:
515
module = _sys._getframemodulename(1) or '__main__'
516
except AttributeError:
517
try:
518
module = _sys._getframe(1).f_globals.get('__name__', '__main__')
519
except (AttributeError, ValueError):
520
pass
521
if module is not None:
522
result.__module__ = module
523
524
return result
525
526
527
########################################################################
528
### Counter
529
########################################################################
530
531
def _count_elements(mapping, iterable):
532
'Tally elements from the iterable.'
533
mapping_get = mapping.get
534
for elem in iterable:
535
mapping[elem] = mapping_get(elem, 0) + 1
536
537
try: # Load C helper function if available
538
from _collections import _count_elements
539
except ImportError:
540
pass
541
542
class Counter(dict):
543
'''Dict subclass for counting hashable items. Sometimes called a bag
544
or multiset. Elements are stored as dictionary keys and their counts
545
are stored as dictionary values.
546
547
>>> c = Counter('abcdeabcdabcaba') # count elements from a string
548
549
>>> c.most_common(3) # three most common elements
550
[('a', 5), ('b', 4), ('c', 3)]
551
>>> sorted(c) # list all unique elements
552
['a', 'b', 'c', 'd', 'e']
553
>>> ''.join(sorted(c.elements())) # list elements with repetitions
554
'aaaaabbbbcccdde'
555
>>> sum(c.values()) # total of all counts
556
15
557
558
>>> c['a'] # count of letter 'a'
559
5
560
>>> for elem in 'shazam': # update counts from an iterable
561
... c[elem] += 1 # by adding 1 to each element's count
562
>>> c['a'] # now there are seven 'a'
563
7
564
>>> del c['b'] # remove all 'b'
565
>>> c['b'] # now there are zero 'b'
566
0
567
568
>>> d = Counter('simsalabim') # make another counter
569
>>> c.update(d) # add in the second counter
570
>>> c['a'] # now there are nine 'a'
571
9
572
573
>>> c.clear() # empty the counter
574
>>> c
575
Counter()
576
577
Note: If a count is set to zero or reduced to zero, it will remain
578
in the counter until the entry is deleted or the counter is cleared:
579
580
>>> c = Counter('aaabbc')
581
>>> c['b'] -= 2 # reduce the count of 'b' by two
582
>>> c.most_common() # 'b' is still in, but its count is zero
583
[('a', 3), ('c', 1), ('b', 0)]
584
585
'''
586
# References:
587
# http://en.wikipedia.org/wiki/Multiset
588
# http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
589
# http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
590
# http://code.activestate.com/recipes/259174/
591
# Knuth, TAOCP Vol. II section 4.6.3
592
593
def __init__(self, iterable=None, /, **kwds):
594
'''Create a new, empty Counter object. And if given, count elements
595
from an input iterable. Or, initialize the count from another mapping
596
of elements to their counts.
597
598
>>> c = Counter() # a new, empty counter
599
>>> c = Counter('gallahad') # a new counter from an iterable
600
>>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping
601
>>> c = Counter(a=4, b=2) # a new counter from keyword args
602
603
'''
604
super().__init__()
605
self.update(iterable, **kwds)
606
607
def __missing__(self, key):
608
'The count of elements not in the Counter is zero.'
609
# Needed so that self[missing_item] does not raise KeyError
610
return 0
611
612
def total(self):
613
'Sum of the counts'
614
return sum(self.values())
615
616
def most_common(self, n=None):
617
'''List the n most common elements and their counts from the most
618
common to the least. If n is None, then list all element counts.
619
620
>>> Counter('abracadabra').most_common(3)
621
[('a', 5), ('b', 2), ('r', 2)]
622
623
'''
624
# Emulate Bag.sortedByCount from Smalltalk
625
if n is None:
626
return sorted(self.items(), key=_itemgetter(1), reverse=True)
627
628
# Lazy import to speedup Python startup time
629
import heapq
630
return heapq.nlargest(n, self.items(), key=_itemgetter(1))
631
632
def elements(self):
633
'''Iterator over elements repeating each as many times as its count.
634
635
>>> c = Counter('ABCABC')
636
>>> sorted(c.elements())
637
['A', 'A', 'B', 'B', 'C', 'C']
638
639
# Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
640
>>> import math
641
>>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
642
>>> math.prod(prime_factors.elements())
643
1836
644
645
Note, if an element's count has been set to zero or is a negative
646
number, elements() will ignore it.
647
648
'''
649
# Emulate Bag.do from Smalltalk and Multiset.begin from C++.
650
return _chain.from_iterable(_starmap(_repeat, self.items()))
651
652
# Override dict methods where necessary
653
654
@classmethod
655
def fromkeys(cls, iterable, v=None):
656
# There is no equivalent method for counters because the semantics
657
# would be ambiguous in cases such as Counter.fromkeys('aaabbc', v=2).
658
# Initializing counters to zero values isn't necessary because zero
659
# is already the default value for counter lookups. Initializing
660
# to one is easily accomplished with Counter(set(iterable)). For
661
# more exotic cases, create a dictionary first using a dictionary
662
# comprehension or dict.fromkeys().
663
raise NotImplementedError(
664
'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
665
666
def update(self, iterable=None, /, **kwds):
667
'''Like dict.update() but add counts instead of replacing them.
668
669
Source can be an iterable, a dictionary, or another Counter instance.
670
671
>>> c = Counter('which')
672
>>> c.update('witch') # add elements from another iterable
673
>>> d = Counter('watch')
674
>>> c.update(d) # add elements from another counter
675
>>> c['h'] # four 'h' in which, witch, and watch
676
4
677
678
'''
679
# The regular dict.update() operation makes no sense here because the
680
# replace behavior results in the some of original untouched counts
681
# being mixed-in with all of the other counts for a mismash that
682
# doesn't have a straight-forward interpretation in most counting
683
# contexts. Instead, we implement straight-addition. Both the inputs
684
# and outputs are allowed to contain zero and negative counts.
685
686
if iterable is not None:
687
if isinstance(iterable, _collections_abc.Mapping):
688
if self:
689
self_get = self.get
690
for elem, count in iterable.items():
691
self[elem] = count + self_get(elem, 0)
692
else:
693
# fast path when counter is empty
694
super().update(iterable)
695
else:
696
_count_elements(self, iterable)
697
if kwds:
698
self.update(kwds)
699
700
def subtract(self, iterable=None, /, **kwds):
701
'''Like dict.update() but subtracts counts instead of replacing them.
702
Counts can be reduced below zero. Both the inputs and outputs are
703
allowed to contain zero and negative counts.
704
705
Source can be an iterable, a dictionary, or another Counter instance.
706
707
>>> c = Counter('which')
708
>>> c.subtract('witch') # subtract elements from another iterable
709
>>> c.subtract(Counter('watch')) # subtract elements from another counter
710
>>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch
711
0
712
>>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch
713
-1
714
715
'''
716
if iterable is not None:
717
self_get = self.get
718
if isinstance(iterable, _collections_abc.Mapping):
719
for elem, count in iterable.items():
720
self[elem] = self_get(elem, 0) - count
721
else:
722
for elem in iterable:
723
self[elem] = self_get(elem, 0) - 1
724
if kwds:
725
self.subtract(kwds)
726
727
def copy(self):
728
'Return a shallow copy.'
729
return self.__class__(self)
730
731
def __reduce__(self):
732
return self.__class__, (dict(self),)
733
734
def __delitem__(self, elem):
735
'Like dict.__delitem__() but does not raise KeyError for missing values.'
736
if elem in self:
737
super().__delitem__(elem)
738
739
def __repr__(self):
740
if not self:
741
return f'{self.__class__.__name__}()'
742
try:
743
# dict() preserves the ordering returned by most_common()
744
d = dict(self.most_common())
745
except TypeError:
746
# handle case where values are not orderable
747
d = dict(self)
748
return f'{self.__class__.__name__}({d!r})'
749
750
# Multiset-style mathematical operations discussed in:
751
# Knuth TAOCP Volume II section 4.6.3 exercise 19
752
# and at http://en.wikipedia.org/wiki/Multiset
753
#
754
# Outputs guaranteed to only include positive counts.
755
#
756
# To strip negative and zero counts, add-in an empty counter:
757
# c += Counter()
758
#
759
# Results are ordered according to when an element is first
760
# encountered in the left operand and then by the order
761
# encountered in the right operand.
762
#
763
# When the multiplicities are all zero or one, multiset operations
764
# are guaranteed to be equivalent to the corresponding operations
765
# for regular sets.
766
# Given counter multisets such as:
767
# cp = Counter(a=1, b=0, c=1)
768
# cq = Counter(c=1, d=0, e=1)
769
# The corresponding regular sets would be:
770
# sp = {'a', 'c'}
771
# sq = {'c', 'e'}
772
# All of the following relations would hold:
773
# set(cp + cq) == sp | sq
774
# set(cp - cq) == sp - sq
775
# set(cp | cq) == sp | sq
776
# set(cp & cq) == sp & sq
777
# (cp == cq) == (sp == sq)
778
# (cp != cq) == (sp != sq)
779
# (cp <= cq) == (sp <= sq)
780
# (cp < cq) == (sp < sq)
781
# (cp >= cq) == (sp >= sq)
782
# (cp > cq) == (sp > sq)
783
784
def __eq__(self, other):
785
'True if all counts agree. Missing counts are treated as zero.'
786
if not isinstance(other, Counter):
787
return NotImplemented
788
return all(self[e] == other[e] for c in (self, other) for e in c)
789
790
def __ne__(self, other):
791
'True if any counts disagree. Missing counts are treated as zero.'
792
if not isinstance(other, Counter):
793
return NotImplemented
794
return not self == other
795
796
def __le__(self, other):
797
'True if all counts in self are a subset of those in other.'
798
if not isinstance(other, Counter):
799
return NotImplemented
800
return all(self[e] <= other[e] for c in (self, other) for e in c)
801
802
def __lt__(self, other):
803
'True if all counts in self are a proper subset of those in other.'
804
if not isinstance(other, Counter):
805
return NotImplemented
806
return self <= other and self != other
807
808
def __ge__(self, other):
809
'True if all counts in self are a superset of those in other.'
810
if not isinstance(other, Counter):
811
return NotImplemented
812
return all(self[e] >= other[e] for c in (self, other) for e in c)
813
814
def __gt__(self, other):
815
'True if all counts in self are a proper superset of those in other.'
816
if not isinstance(other, Counter):
817
return NotImplemented
818
return self >= other and self != other
819
820
def __add__(self, other):
821
'''Add counts from two counters.
822
823
>>> Counter('abbb') + Counter('bcc')
824
Counter({'b': 4, 'c': 2, 'a': 1})
825
826
'''
827
if not isinstance(other, Counter):
828
return NotImplemented
829
result = Counter()
830
for elem, count in self.items():
831
newcount = count + other[elem]
832
if newcount > 0:
833
result[elem] = newcount
834
for elem, count in other.items():
835
if elem not in self and count > 0:
836
result[elem] = count
837
return result
838
839
def __sub__(self, other):
840
''' Subtract count, but keep only results with positive counts.
841
842
>>> Counter('abbbc') - Counter('bccd')
843
Counter({'b': 2, 'a': 1})
844
845
'''
846
if not isinstance(other, Counter):
847
return NotImplemented
848
result = Counter()
849
for elem, count in self.items():
850
newcount = count - other[elem]
851
if newcount > 0:
852
result[elem] = newcount
853
for elem, count in other.items():
854
if elem not in self and count < 0:
855
result[elem] = 0 - count
856
return result
857
858
def __or__(self, other):
859
'''Union is the maximum of value in either of the input counters.
860
861
>>> Counter('abbb') | Counter('bcc')
862
Counter({'b': 3, 'c': 2, 'a': 1})
863
864
'''
865
if not isinstance(other, Counter):
866
return NotImplemented
867
result = Counter()
868
for elem, count in self.items():
869
other_count = other[elem]
870
newcount = other_count if count < other_count else count
871
if newcount > 0:
872
result[elem] = newcount
873
for elem, count in other.items():
874
if elem not in self and count > 0:
875
result[elem] = count
876
return result
877
878
def __and__(self, other):
879
''' Intersection is the minimum of corresponding counts.
880
881
>>> Counter('abbb') & Counter('bcc')
882
Counter({'b': 1})
883
884
'''
885
if not isinstance(other, Counter):
886
return NotImplemented
887
result = Counter()
888
for elem, count in self.items():
889
other_count = other[elem]
890
newcount = count if count < other_count else other_count
891
if newcount > 0:
892
result[elem] = newcount
893
return result
894
895
def __pos__(self):
896
'Adds an empty counter, effectively stripping negative and zero counts'
897
result = Counter()
898
for elem, count in self.items():
899
if count > 0:
900
result[elem] = count
901
return result
902
903
def __neg__(self):
904
'''Subtracts from an empty counter. Strips positive and zero counts,
905
and flips the sign on negative counts.
906
907
'''
908
result = Counter()
909
for elem, count in self.items():
910
if count < 0:
911
result[elem] = 0 - count
912
return result
913
914
def _keep_positive(self):
915
'''Internal method to strip elements with a negative or zero count'''
916
nonpositive = [elem for elem, count in self.items() if not count > 0]
917
for elem in nonpositive:
918
del self[elem]
919
return self
920
921
def __iadd__(self, other):
922
'''Inplace add from another counter, keeping only positive counts.
923
924
>>> c = Counter('abbb')
925
>>> c += Counter('bcc')
926
>>> c
927
Counter({'b': 4, 'c': 2, 'a': 1})
928
929
'''
930
for elem, count in other.items():
931
self[elem] += count
932
return self._keep_positive()
933
934
def __isub__(self, other):
935
'''Inplace subtract counter, but keep only results with positive counts.
936
937
>>> c = Counter('abbbc')
938
>>> c -= Counter('bccd')
939
>>> c
940
Counter({'b': 2, 'a': 1})
941
942
'''
943
for elem, count in other.items():
944
self[elem] -= count
945
return self._keep_positive()
946
947
def __ior__(self, other):
948
'''Inplace union is the maximum of value from either counter.
949
950
>>> c = Counter('abbb')
951
>>> c |= Counter('bcc')
952
>>> c
953
Counter({'b': 3, 'c': 2, 'a': 1})
954
955
'''
956
for elem, other_count in other.items():
957
count = self[elem]
958
if other_count > count:
959
self[elem] = other_count
960
return self._keep_positive()
961
962
def __iand__(self, other):
963
'''Inplace intersection is the minimum of corresponding counts.
964
965
>>> c = Counter('abbb')
966
>>> c &= Counter('bcc')
967
>>> c
968
Counter({'b': 1})
969
970
'''
971
for elem, count in self.items():
972
other_count = other[elem]
973
if other_count < count:
974
self[elem] = other_count
975
return self._keep_positive()
976
977
978
########################################################################
979
### ChainMap
980
########################################################################
981
982
class ChainMap(_collections_abc.MutableMapping):
983
''' A ChainMap groups multiple dicts (or other mappings) together
984
to create a single, updateable view.
985
986
The underlying mappings are stored in a list. That list is public and can
987
be accessed or updated using the *maps* attribute. There is no other
988
state.
989
990
Lookups search the underlying mappings successively until a key is found.
991
In contrast, writes, updates, and deletions only operate on the first
992
mapping.
993
994
'''
995
996
def __init__(self, *maps):
997
'''Initialize a ChainMap by setting *maps* to the given mappings.
998
If no mappings are provided, a single empty dictionary is used.
999
1000
'''
1001
self.maps = list(maps) or [{}] # always at least one map
1002
1003
def __missing__(self, key):
1004
raise KeyError(key)
1005
1006
def __getitem__(self, key):
1007
for mapping in self.maps:
1008
try:
1009
return mapping[key] # can't use 'key in mapping' with defaultdict
1010
except KeyError:
1011
pass
1012
return self.__missing__(key) # support subclasses that define __missing__
1013
1014
def get(self, key, default=None):
1015
return self[key] if key in self else default
1016
1017
def __len__(self):
1018
return len(set().union(*self.maps)) # reuses stored hash values if possible
1019
1020
def __iter__(self):
1021
d = {}
1022
for mapping in map(dict.fromkeys, reversed(self.maps)):
1023
d |= mapping # reuses stored hash values if possible
1024
return iter(d)
1025
1026
def __contains__(self, key):
1027
return any(key in m for m in self.maps)
1028
1029
def __bool__(self):
1030
return any(self.maps)
1031
1032
@_recursive_repr()
1033
def __repr__(self):
1034
return f'{self.__class__.__name__}({", ".join(map(repr, self.maps))})'
1035
1036
@classmethod
1037
def fromkeys(cls, iterable, *args):
1038
'Create a ChainMap with a single dict created from the iterable.'
1039
return cls(dict.fromkeys(iterable, *args))
1040
1041
def copy(self):
1042
'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
1043
return self.__class__(self.maps[0].copy(), *self.maps[1:])
1044
1045
__copy__ = copy
1046
1047
def new_child(self, m=None, **kwargs): # like Django's Context.push()
1048
'''New ChainMap with a new map followed by all previous maps.
1049
If no map is provided, an empty dict is used.
1050
Keyword arguments update the map or new empty dict.
1051
'''
1052
if m is None:
1053
m = kwargs
1054
elif kwargs:
1055
m.update(kwargs)
1056
return self.__class__(m, *self.maps)
1057
1058
@property
1059
def parents(self): # like Django's Context.pop()
1060
'New ChainMap from maps[1:].'
1061
return self.__class__(*self.maps[1:])
1062
1063
def __setitem__(self, key, value):
1064
self.maps[0][key] = value
1065
1066
def __delitem__(self, key):
1067
try:
1068
del self.maps[0][key]
1069
except KeyError:
1070
raise KeyError(f'Key not found in the first mapping: {key!r}')
1071
1072
def popitem(self):
1073
'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
1074
try:
1075
return self.maps[0].popitem()
1076
except KeyError:
1077
raise KeyError('No keys found in the first mapping.')
1078
1079
def pop(self, key, *args):
1080
'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
1081
try:
1082
return self.maps[0].pop(key, *args)
1083
except KeyError:
1084
raise KeyError(f'Key not found in the first mapping: {key!r}')
1085
1086
def clear(self):
1087
'Clear maps[0], leaving maps[1:] intact.'
1088
self.maps[0].clear()
1089
1090
def __ior__(self, other):
1091
self.maps[0].update(other)
1092
return self
1093
1094
def __or__(self, other):
1095
if not isinstance(other, _collections_abc.Mapping):
1096
return NotImplemented
1097
m = self.copy()
1098
m.maps[0].update(other)
1099
return m
1100
1101
def __ror__(self, other):
1102
if not isinstance(other, _collections_abc.Mapping):
1103
return NotImplemented
1104
m = dict(other)
1105
for child in reversed(self.maps):
1106
m.update(child)
1107
return self.__class__(m)
1108
1109
1110
################################################################################
1111
### UserDict
1112
################################################################################
1113
1114
class UserDict(_collections_abc.MutableMapping):
1115
1116
# Start by filling-out the abstract methods
1117
def __init__(self, dict=None, /, **kwargs):
1118
self.data = {}
1119
if dict is not None:
1120
self.update(dict)
1121
if kwargs:
1122
self.update(kwargs)
1123
1124
def __len__(self):
1125
return len(self.data)
1126
1127
def __getitem__(self, key):
1128
if key in self.data:
1129
return self.data[key]
1130
if hasattr(self.__class__, "__missing__"):
1131
return self.__class__.__missing__(self, key)
1132
raise KeyError(key)
1133
1134
def __setitem__(self, key, item):
1135
self.data[key] = item
1136
1137
def __delitem__(self, key):
1138
del self.data[key]
1139
1140
def __iter__(self):
1141
return iter(self.data)
1142
1143
# Modify __contains__ and get() to work like dict
1144
# does when __missing__ is present.
1145
def __contains__(self, key):
1146
return key in self.data
1147
1148
def get(self, key, default=None):
1149
if key in self:
1150
return self[key]
1151
return default
1152
1153
1154
# Now, add the methods in dicts but not in MutableMapping
1155
def __repr__(self):
1156
return repr(self.data)
1157
1158
def __or__(self, other):
1159
if isinstance(other, UserDict):
1160
return self.__class__(self.data | other.data)
1161
if isinstance(other, dict):
1162
return self.__class__(self.data | other)
1163
return NotImplemented
1164
1165
def __ror__(self, other):
1166
if isinstance(other, UserDict):
1167
return self.__class__(other.data | self.data)
1168
if isinstance(other, dict):
1169
return self.__class__(other | self.data)
1170
return NotImplemented
1171
1172
def __ior__(self, other):
1173
if isinstance(other, UserDict):
1174
self.data |= other.data
1175
else:
1176
self.data |= other
1177
return self
1178
1179
def __copy__(self):
1180
inst = self.__class__.__new__(self.__class__)
1181
inst.__dict__.update(self.__dict__)
1182
# Create a copy and avoid triggering descriptors
1183
inst.__dict__["data"] = self.__dict__["data"].copy()
1184
return inst
1185
1186
def copy(self):
1187
if self.__class__ is UserDict:
1188
return UserDict(self.data.copy())
1189
import copy
1190
data = self.data
1191
try:
1192
self.data = {}
1193
c = copy.copy(self)
1194
finally:
1195
self.data = data
1196
c.update(self)
1197
return c
1198
1199
@classmethod
1200
def fromkeys(cls, iterable, value=None):
1201
d = cls()
1202
for key in iterable:
1203
d[key] = value
1204
return d
1205
1206
1207
################################################################################
1208
### UserList
1209
################################################################################
1210
1211
class UserList(_collections_abc.MutableSequence):
1212
"""A more or less complete user-defined wrapper around list objects."""
1213
1214
def __init__(self, initlist=None):
1215
self.data = []
1216
if initlist is not None:
1217
# XXX should this accept an arbitrary sequence?
1218
if type(initlist) == type(self.data):
1219
self.data[:] = initlist
1220
elif isinstance(initlist, UserList):
1221
self.data[:] = initlist.data[:]
1222
else:
1223
self.data = list(initlist)
1224
1225
def __repr__(self):
1226
return repr(self.data)
1227
1228
def __lt__(self, other):
1229
return self.data < self.__cast(other)
1230
1231
def __le__(self, other):
1232
return self.data <= self.__cast(other)
1233
1234
def __eq__(self, other):
1235
return self.data == self.__cast(other)
1236
1237
def __gt__(self, other):
1238
return self.data > self.__cast(other)
1239
1240
def __ge__(self, other):
1241
return self.data >= self.__cast(other)
1242
1243
def __cast(self, other):
1244
return other.data if isinstance(other, UserList) else other
1245
1246
def __contains__(self, item):
1247
return item in self.data
1248
1249
def __len__(self):
1250
return len(self.data)
1251
1252
def __getitem__(self, i):
1253
if isinstance(i, slice):
1254
return self.__class__(self.data[i])
1255
else:
1256
return self.data[i]
1257
1258
def __setitem__(self, i, item):
1259
self.data[i] = item
1260
1261
def __delitem__(self, i):
1262
del self.data[i]
1263
1264
def __add__(self, other):
1265
if isinstance(other, UserList):
1266
return self.__class__(self.data + other.data)
1267
elif isinstance(other, type(self.data)):
1268
return self.__class__(self.data + other)
1269
return self.__class__(self.data + list(other))
1270
1271
def __radd__(self, other):
1272
if isinstance(other, UserList):
1273
return self.__class__(other.data + self.data)
1274
elif isinstance(other, type(self.data)):
1275
return self.__class__(other + self.data)
1276
return self.__class__(list(other) + self.data)
1277
1278
def __iadd__(self, other):
1279
if isinstance(other, UserList):
1280
self.data += other.data
1281
elif isinstance(other, type(self.data)):
1282
self.data += other
1283
else:
1284
self.data += list(other)
1285
return self
1286
1287
def __mul__(self, n):
1288
return self.__class__(self.data * n)
1289
1290
__rmul__ = __mul__
1291
1292
def __imul__(self, n):
1293
self.data *= n
1294
return self
1295
1296
def __copy__(self):
1297
inst = self.__class__.__new__(self.__class__)
1298
inst.__dict__.update(self.__dict__)
1299
# Create a copy and avoid triggering descriptors
1300
inst.__dict__["data"] = self.__dict__["data"][:]
1301
return inst
1302
1303
def append(self, item):
1304
self.data.append(item)
1305
1306
def insert(self, i, item):
1307
self.data.insert(i, item)
1308
1309
def pop(self, i=-1):
1310
return self.data.pop(i)
1311
1312
def remove(self, item):
1313
self.data.remove(item)
1314
1315
def clear(self):
1316
self.data.clear()
1317
1318
def copy(self):
1319
return self.__class__(self)
1320
1321
def count(self, item):
1322
return self.data.count(item)
1323
1324
def index(self, item, *args):
1325
return self.data.index(item, *args)
1326
1327
def reverse(self):
1328
self.data.reverse()
1329
1330
def sort(self, /, *args, **kwds):
1331
self.data.sort(*args, **kwds)
1332
1333
def extend(self, other):
1334
if isinstance(other, UserList):
1335
self.data.extend(other.data)
1336
else:
1337
self.data.extend(other)
1338
1339
1340
################################################################################
1341
### UserString
1342
################################################################################
1343
1344
class UserString(_collections_abc.Sequence):
1345
1346
def __init__(self, seq):
1347
if isinstance(seq, str):
1348
self.data = seq
1349
elif isinstance(seq, UserString):
1350
self.data = seq.data[:]
1351
else:
1352
self.data = str(seq)
1353
1354
def __str__(self):
1355
return str(self.data)
1356
1357
def __repr__(self):
1358
return repr(self.data)
1359
1360
def __int__(self):
1361
return int(self.data)
1362
1363
def __float__(self):
1364
return float(self.data)
1365
1366
def __complex__(self):
1367
return complex(self.data)
1368
1369
def __hash__(self):
1370
return hash(self.data)
1371
1372
def __getnewargs__(self):
1373
return (self.data[:],)
1374
1375
def __eq__(self, string):
1376
if isinstance(string, UserString):
1377
return self.data == string.data
1378
return self.data == string
1379
1380
def __lt__(self, string):
1381
if isinstance(string, UserString):
1382
return self.data < string.data
1383
return self.data < string
1384
1385
def __le__(self, string):
1386
if isinstance(string, UserString):
1387
return self.data <= string.data
1388
return self.data <= string
1389
1390
def __gt__(self, string):
1391
if isinstance(string, UserString):
1392
return self.data > string.data
1393
return self.data > string
1394
1395
def __ge__(self, string):
1396
if isinstance(string, UserString):
1397
return self.data >= string.data
1398
return self.data >= string
1399
1400
def __contains__(self, char):
1401
if isinstance(char, UserString):
1402
char = char.data
1403
return char in self.data
1404
1405
def __len__(self):
1406
return len(self.data)
1407
1408
def __getitem__(self, index):
1409
return self.__class__(self.data[index])
1410
1411
def __add__(self, other):
1412
if isinstance(other, UserString):
1413
return self.__class__(self.data + other.data)
1414
elif isinstance(other, str):
1415
return self.__class__(self.data + other)
1416
return self.__class__(self.data + str(other))
1417
1418
def __radd__(self, other):
1419
if isinstance(other, str):
1420
return self.__class__(other + self.data)
1421
return self.__class__(str(other) + self.data)
1422
1423
def __mul__(self, n):
1424
return self.__class__(self.data * n)
1425
1426
__rmul__ = __mul__
1427
1428
def __mod__(self, args):
1429
return self.__class__(self.data % args)
1430
1431
def __rmod__(self, template):
1432
return self.__class__(str(template) % self)
1433
1434
# the following methods are defined in alphabetical order:
1435
def capitalize(self):
1436
return self.__class__(self.data.capitalize())
1437
1438
def casefold(self):
1439
return self.__class__(self.data.casefold())
1440
1441
def center(self, width, *args):
1442
return self.__class__(self.data.center(width, *args))
1443
1444
def count(self, sub, start=0, end=_sys.maxsize):
1445
if isinstance(sub, UserString):
1446
sub = sub.data
1447
return self.data.count(sub, start, end)
1448
1449
def removeprefix(self, prefix, /):
1450
if isinstance(prefix, UserString):
1451
prefix = prefix.data
1452
return self.__class__(self.data.removeprefix(prefix))
1453
1454
def removesuffix(self, suffix, /):
1455
if isinstance(suffix, UserString):
1456
suffix = suffix.data
1457
return self.__class__(self.data.removesuffix(suffix))
1458
1459
def encode(self, encoding='utf-8', errors='strict'):
1460
encoding = 'utf-8' if encoding is None else encoding
1461
errors = 'strict' if errors is None else errors
1462
return self.data.encode(encoding, errors)
1463
1464
def endswith(self, suffix, start=0, end=_sys.maxsize):
1465
return self.data.endswith(suffix, start, end)
1466
1467
def expandtabs(self, tabsize=8):
1468
return self.__class__(self.data.expandtabs(tabsize))
1469
1470
def find(self, sub, start=0, end=_sys.maxsize):
1471
if isinstance(sub, UserString):
1472
sub = sub.data
1473
return self.data.find(sub, start, end)
1474
1475
def format(self, /, *args, **kwds):
1476
return self.data.format(*args, **kwds)
1477
1478
def format_map(self, mapping):
1479
return self.data.format_map(mapping)
1480
1481
def index(self, sub, start=0, end=_sys.maxsize):
1482
return self.data.index(sub, start, end)
1483
1484
def isalpha(self):
1485
return self.data.isalpha()
1486
1487
def isalnum(self):
1488
return self.data.isalnum()
1489
1490
def isascii(self):
1491
return self.data.isascii()
1492
1493
def isdecimal(self):
1494
return self.data.isdecimal()
1495
1496
def isdigit(self):
1497
return self.data.isdigit()
1498
1499
def isidentifier(self):
1500
return self.data.isidentifier()
1501
1502
def islower(self):
1503
return self.data.islower()
1504
1505
def isnumeric(self):
1506
return self.data.isnumeric()
1507
1508
def isprintable(self):
1509
return self.data.isprintable()
1510
1511
def isspace(self):
1512
return self.data.isspace()
1513
1514
def istitle(self):
1515
return self.data.istitle()
1516
1517
def isupper(self):
1518
return self.data.isupper()
1519
1520
def join(self, seq):
1521
return self.data.join(seq)
1522
1523
def ljust(self, width, *args):
1524
return self.__class__(self.data.ljust(width, *args))
1525
1526
def lower(self):
1527
return self.__class__(self.data.lower())
1528
1529
def lstrip(self, chars=None):
1530
return self.__class__(self.data.lstrip(chars))
1531
1532
maketrans = str.maketrans
1533
1534
def partition(self, sep):
1535
return self.data.partition(sep)
1536
1537
def replace(self, old, new, maxsplit=-1):
1538
if isinstance(old, UserString):
1539
old = old.data
1540
if isinstance(new, UserString):
1541
new = new.data
1542
return self.__class__(self.data.replace(old, new, maxsplit))
1543
1544
def rfind(self, sub, start=0, end=_sys.maxsize):
1545
if isinstance(sub, UserString):
1546
sub = sub.data
1547
return self.data.rfind(sub, start, end)
1548
1549
def rindex(self, sub, start=0, end=_sys.maxsize):
1550
return self.data.rindex(sub, start, end)
1551
1552
def rjust(self, width, *args):
1553
return self.__class__(self.data.rjust(width, *args))
1554
1555
def rpartition(self, sep):
1556
return self.data.rpartition(sep)
1557
1558
def rstrip(self, chars=None):
1559
return self.__class__(self.data.rstrip(chars))
1560
1561
def split(self, sep=None, maxsplit=-1):
1562
return self.data.split(sep, maxsplit)
1563
1564
def rsplit(self, sep=None, maxsplit=-1):
1565
return self.data.rsplit(sep, maxsplit)
1566
1567
def splitlines(self, keepends=False):
1568
return self.data.splitlines(keepends)
1569
1570
def startswith(self, prefix, start=0, end=_sys.maxsize):
1571
return self.data.startswith(prefix, start, end)
1572
1573
def strip(self, chars=None):
1574
return self.__class__(self.data.strip(chars))
1575
1576
def swapcase(self):
1577
return self.__class__(self.data.swapcase())
1578
1579
def title(self):
1580
return self.__class__(self.data.title())
1581
1582
def translate(self, *args):
1583
return self.__class__(self.data.translate(*args))
1584
1585
def upper(self):
1586
return self.__class__(self.data.upper())
1587
1588
def zfill(self, width):
1589
return self.__class__(self.data.zfill(width))
1590
1591