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