ยปCore Development>Code coverage>Lib/collections.py

Python code coverage for Lib/collections.py

#countcontent
1n/a__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
2n/a 'UserString', 'Counter', 'OrderedDict']
3n/a# For bootstrapping reasons, the collection ABCs are defined in _abcoll.py.
4n/a# They should however be considered an integral part of collections.py.
5n/afrom _abcoll import *
6n/aimport _abcoll
7n/a__all__ += _abcoll.__all__
8n/a
9n/afrom _collections import deque, defaultdict
10n/afrom operator import itemgetter as _itemgetter
11n/afrom keyword import iskeyword as _iskeyword
12n/aimport sys as _sys
13n/aimport heapq as _heapq
14n/afrom weakref import proxy as _proxy
15n/afrom itertools import repeat as _repeat, chain as _chain, starmap as _starmap
16n/afrom reprlib import recursive_repr as _recursive_repr
17n/a
18n/a################################################################################
19n/a### OrderedDict
20n/a################################################################################
21n/a
22n/aclass _Link(object):
23n/a __slots__ = 'prev', 'next', 'key', '__weakref__'
24n/a
25n/aclass OrderedDict(dict):
26n/a 'Dictionary that remembers insertion order'
27n/a # An inherited dict maps keys to values.
28n/a # The inherited dict provides __getitem__, __len__, __contains__, and get.
29n/a # The remaining methods are order-aware.
30n/a # Big-O running times for all methods are the same as for regular dictionaries.
31n/a
32n/a # The internal self.__map dictionary maps keys to links in a doubly linked list.
33n/a # The circular doubly linked list starts and ends with a sentinel element.
34n/a # The sentinel element never gets deleted (this simplifies the algorithm).
35n/a # The sentinel is stored in self.__hardroot with a weakref proxy in self.__root.
36n/a # The prev/next links are weakref proxies (to prevent circular references).
37n/a # Individual links are kept alive by the hard reference in self.__map.
38n/a # Those hard references disappear when a key is deleted from an OrderedDict.
39n/a
40n/a def __init__(self, *args, **kwds):
41n/a '''Initialize an ordered dictionary. Signature is the same as for
42n/a regular dictionaries, but keyword arguments are not recommended
43n/a because their insertion order is arbitrary.
44n/a
45n/a '''
46n/a if len(args) > 1:
47n/a raise TypeError('expected at most 1 arguments, got %d' % len(args))
48n/a try:
49n/a self.__root
50n/a except AttributeError:
51n/a self.__hardroot = _Link()
52n/a self.__root = root = _proxy(self.__hardroot)
53n/a root.prev = root.next = root
54n/a self.__map = {}
55n/a self.__update(*args, **kwds)
56n/a
57n/a def __setitem__(self, key, value,
58n/a dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link):
59n/a 'od.__setitem__(i, y) <==> od[i]=y'
60n/a # Setting a new item creates a new link which goes at the end of the linked
61n/a # list, and the inherited dictionary is updated with the new key/value pair.
62n/a if key not in self:
63n/a self.__map[key] = link = Link()
64n/a root = self.__root
65n/a last = root.prev
66n/a link.prev, link.next, link.key = last, root, key
67n/a last.next = link
68n/a root.prev = proxy(link)
69n/a dict_setitem(self, key, value)
70n/a
71n/a def __delitem__(self, key, dict_delitem=dict.__delitem__):
72n/a 'od.__delitem__(y) <==> del od[y]'
73n/a # Deleting an existing item uses self.__map to find the link which is
74n/a # then removed by updating the links in the predecessor and successor nodes.
75n/a dict_delitem(self, key)
76n/a link = self.__map.pop(key)
77n/a link_prev = link.prev
78n/a link_next = link.next
79n/a link_prev.next = link_next
80n/a link_next.prev = link_prev
81n/a
82n/a def __iter__(self):
83n/a 'od.__iter__() <==> iter(od)'
84n/a # Traverse the linked list in order.
85n/a root = self.__root
86n/a curr = root.next
87n/a while curr is not root:
88n/a yield curr.key
89n/a curr = curr.next
90n/a
91n/a def __reversed__(self):
92n/a 'od.__reversed__() <==> reversed(od)'
93n/a # Traverse the linked list in reverse order.
94n/a root = self.__root
95n/a curr = root.prev
96n/a while curr is not root:
97n/a yield curr.key
98n/a curr = curr.prev
99n/a
100n/a def clear(self):
101n/a 'od.clear() -> None. Remove all items from od.'
102n/a root = self.__root
103n/a root.prev = root.next = root
104n/a self.__map.clear()
105n/a dict.clear(self)
106n/a
107n/a def popitem(self, last=True):
108n/a '''od.popitem() -> (k, v), return and remove a (key, value) pair.
109n/a Pairs are returned in LIFO order if last is true or FIFO order if false.
110n/a
111n/a '''
112n/a if not self:
113n/a raise KeyError('dictionary is empty')
114n/a root = self.__root
115n/a if last:
116n/a link = root.prev
117n/a link_prev = link.prev
118n/a link_prev.next = root
119n/a root.prev = link_prev
120n/a else:
121n/a link = root.next
122n/a link_next = link.next
123n/a root.next = link_next
124n/a link_next.prev = root
125n/a key = link.key
126n/a del self.__map[key]
127n/a value = dict.pop(self, key)
128n/a return key, value
129n/a
130n/a def move_to_end(self, key, last=True):
131n/a '''Move an existing element to the end (or beginning if last==False).
132n/a
133n/a Raises KeyError if the element does not exist.
134n/a When last=True, acts like a fast version of self[key]=self.pop(key).
135n/a
136n/a '''
137n/a link = self.__map[key]
138n/a link_prev = link.prev
139n/a link_next = link.next
140n/a link_prev.next = link_next
141n/a link_next.prev = link_prev
142n/a root = self.__root
143n/a if last:
144n/a last = root.prev
145n/a link.prev = last
146n/a link.next = root
147n/a last.next = root.prev = link
148n/a else:
149n/a first = root.next
150n/a link.prev = root
151n/a link.next = first
152n/a root.next = first.prev = link
153n/a
154n/a def __reduce__(self):
155n/a 'Return state information for pickling'
156n/a items = [[k, self[k]] for k in self]
157n/a tmp = self.__map, self.__root, self.__hardroot
158n/a del self.__map, self.__root, self.__hardroot
159n/a inst_dict = vars(self).copy()
160n/a self.__map, self.__root, self.__hardroot = tmp
161n/a if inst_dict:
162n/a return (self.__class__, (items,), inst_dict)
163n/a return self.__class__, (items,)
164n/a
165n/a def __sizeof__(self):
166n/a sizeof = _sys.getsizeof
167n/a n = len(self) + 1 # number of links including root
168n/a size = sizeof(self.__dict__) # instance dictionary
169n/a size += sizeof(self.__map) * 2 # internal dict and inherited dict
170n/a size += sizeof(self.__hardroot) * n # link objects
171n/a size += sizeof(self.__root) * n # proxy objects
172n/a return size
173n/a
174n/a update = __update = MutableMapping.update
175n/a keys = MutableMapping.keys
176n/a values = MutableMapping.values
177n/a items = MutableMapping.items
178n/a __ne__ = MutableMapping.__ne__
179n/a
180n/a __marker = object()
181n/a
182n/a def pop(self, key, default=__marker):
183n/a if key in self:
184n/a result = self[key]
185n/a del self[key]
186n/a return result
187n/a if default is self.__marker:
188n/a raise KeyError(key)
189n/a return default
190n/a
191n/a def setdefault(self, key, default=None):
192n/a 'OD.setdefault(k[,d]) -> OD.get(k,d), also set OD[k]=d if k not in OD'
193n/a if key in self:
194n/a return self[key]
195n/a self[key] = default
196n/a return default
197n/a
198n/a @_recursive_repr()
199n/a def __repr__(self):
200n/a 'od.__repr__() <==> repr(od)'
201n/a if not self:
202n/a return '%s()' % (self.__class__.__name__,)
203n/a return '%s(%r)' % (self.__class__.__name__, list(self.items()))
204n/a
205n/a def copy(self):
206n/a 'od.copy() -> a shallow copy of od'
207n/a return self.__class__(self)
208n/a
209n/a @classmethod
210n/a def fromkeys(cls, iterable, value=None):
211n/a '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
212n/a and values equal to v (which defaults to None).
213n/a
214n/a '''
215n/a d = cls()
216n/a for key in iterable:
217n/a d[key] = value
218n/a return d
219n/a
220n/a def __eq__(self, other):
221n/a '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
222n/a while comparison to a regular mapping is order-insensitive.
223n/a
224n/a '''
225n/a if isinstance(other, OrderedDict):
226n/a return len(self)==len(other) and \
227n/a all(p==q for p, q in zip(self.items(), other.items()))
228n/a return dict.__eq__(self, other)
229n/a
230n/a
231n/a################################################################################
232n/a### namedtuple
233n/a################################################################################
234n/a
235n/adef namedtuple(typename, field_names, verbose=False, rename=False):
236n/a """Returns a new subclass of tuple with named fields.
237n/a
238n/a >>> Point = namedtuple('Point', 'x y')
239n/a >>> Point.__doc__ # docstring for the new class
240n/a 'Point(x, y)'
241n/a >>> p = Point(11, y=22) # instantiate with positional args or keywords
242n/a >>> p[0] + p[1] # indexable like a plain tuple
243n/a 33
244n/a >>> x, y = p # unpack like a regular tuple
245n/a >>> x, y
246n/a (11, 22)
247n/a >>> p.x + p.y # fields also accessable by name
248n/a 33
249n/a >>> d = p._asdict() # convert to a dictionary
250n/a >>> d['x']
251n/a 11
252n/a >>> Point(**d) # convert from a dictionary
253n/a Point(x=11, y=22)
254n/a >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields
255n/a Point(x=100, y=22)
256n/a
257n/a """
258n/a
259n/a # Parse and validate the field names. Validation serves two purposes,
260n/a # generating informative error messages and preventing template injection attacks.
261n/a if isinstance(field_names, str):
262n/a field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
263n/a field_names = tuple(map(str, field_names))
264n/a if rename:
265n/a names = list(field_names)
266n/a seen = set()
267n/a for i, name in enumerate(names):
268n/a if (not all(c.isalnum() or c=='_' for c in name) or _iskeyword(name)
269n/a or not name or name[0].isdigit() or name.startswith('_')
270n/a or name in seen):
271n/a names[i] = '_%d' % i
272n/a seen.add(name)
273n/a field_names = tuple(names)
274n/a for name in (typename,) + field_names:
275n/a if not all(c.isalnum() or c=='_' for c in name):
276n/a raise ValueError('Type names and field names can only contain alphanumeric characters and underscores: %r' % name)
277n/a if _iskeyword(name):
278n/a raise ValueError('Type names and field names cannot be a keyword: %r' % name)
279n/a if name[0].isdigit():
280n/a raise ValueError('Type names and field names cannot start with a number: %r' % name)
281n/a seen_names = set()
282n/a for name in field_names:
283n/a if name.startswith('_') and not rename:
284n/a raise ValueError('Field names cannot start with an underscore: %r' % name)
285n/a if name in seen_names:
286n/a raise ValueError('Encountered duplicate field name: %r' % name)
287n/a seen_names.add(name)
288n/a
289n/a # Create and fill-in the class template
290n/a numfields = len(field_names)
291n/a argtxt = repr(field_names).replace("'", "")[1:-1] # tuple repr without parens or quotes
292n/a reprtxt = ', '.join('%s=%%r' % name for name in field_names)
293n/a template = '''class %(typename)s(tuple):
294n/a '%(typename)s(%(argtxt)s)' \n
295n/a __slots__ = () \n
296n/a _fields = %(field_names)r \n
297n/a def __new__(_cls, %(argtxt)s):
298n/a 'Create new instance of %(typename)s(%(argtxt)s)'
299n/a return _tuple.__new__(_cls, (%(argtxt)s)) \n
300n/a @classmethod
301n/a def _make(cls, iterable, new=tuple.__new__, len=len):
302n/a 'Make a new %(typename)s object from a sequence or iterable'
303n/a result = new(cls, iterable)
304n/a if len(result) != %(numfields)d:
305n/a raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
306n/a return result \n
307n/a def __repr__(self):
308n/a 'Return a nicely formatted representation string'
309n/a return self.__class__.__name__ + '(%(reprtxt)s)' %% self \n
310n/a def _asdict(self):
311n/a 'Return a new OrderedDict which maps field names to their values'
312n/a return OrderedDict(zip(self._fields, self)) \n
313n/a def _replace(_self, **kwds):
314n/a 'Return a new %(typename)s object replacing specified fields with new values'
315n/a result = _self._make(map(kwds.pop, %(field_names)r, _self))
316n/a if kwds:
317n/a raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
318n/a return result \n
319n/a def __getnewargs__(self):
320n/a 'Return self as a plain tuple. Used by copy and pickle.'
321n/a return tuple(self) \n\n''' % locals()
322n/a for i, name in enumerate(field_names):
323n/a template += " %s = _property(_itemgetter(%d), doc='Alias for field number %d')\n" % (name, i, i)
324n/a if verbose:
325n/a print(template)
326n/a
327n/a # Execute the template string in a temporary namespace and
328n/a # support tracing utilities by setting a value for frame.f_globals['__name__']
329n/a namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
330n/a OrderedDict=OrderedDict, _property=property, _tuple=tuple)
331n/a try:
332n/a exec(template, namespace)
333n/a except SyntaxError as e:
334n/a raise SyntaxError(e.msg + ':\n\n' + template)
335n/a result = namespace[typename]
336n/a
337n/a # For pickling to work, the __module__ variable needs to be set to the frame
338n/a # where the named tuple is created. Bypass this step in enviroments where
339n/a # sys._getframe is not defined (Jython for example) or sys._getframe is not
340n/a # defined for arguments greater than 0 (IronPython).
341n/a try:
342n/a result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
343n/a except (AttributeError, ValueError):
344n/a pass
345n/a
346n/a return result
347n/a
348n/a
349n/a########################################################################
350n/a### Counter
351n/a########################################################################
352n/a
353n/adef _count_elements(mapping, iterable):
354n/a 'Tally elements from the iterable.'
355n/a mapping_get = mapping.get
356n/a for elem in iterable:
357n/a mapping[elem] = mapping_get(elem, 0) + 1
358n/a
359n/atry: # Load C helper function if available
360n/a from _collections import _count_elements
361n/aexcept ImportError:
362n/a pass
363n/a
364n/aclass Counter(dict):
365n/a '''Dict subclass for counting hashable items. Sometimes called a bag
366n/a or multiset. Elements are stored as dictionary keys and their counts
367n/a are stored as dictionary values.
368n/a
369n/a >>> c = Counter('abcdeabcdabcaba') # count elements from a string
370n/a
371n/a >>> c.most_common(3) # three most common elements
372n/a [('a', 5), ('b', 4), ('c', 3)]
373n/a >>> sorted(c) # list all unique elements
374n/a ['a', 'b', 'c', 'd', 'e']
375n/a >>> ''.join(sorted(c.elements())) # list elements with repetitions
376n/a 'aaaaabbbbcccdde'
377n/a >>> sum(c.values()) # total of all counts
378n/a 15
379n/a
380n/a >>> c['a'] # count of letter 'a'
381n/a 5
382n/a >>> for elem in 'shazam': # update counts from an iterable
383n/a ... c[elem] += 1 # by adding 1 to each element's count
384n/a >>> c['a'] # now there are seven 'a'
385n/a 7
386n/a >>> del c['b'] # remove all 'b'
387n/a >>> c['b'] # now there are zero 'b'
388n/a 0
389n/a
390n/a >>> d = Counter('simsalabim') # make another counter
391n/a >>> c.update(d) # add in the second counter
392n/a >>> c['a'] # now there are nine 'a'
393n/a 9
394n/a
395n/a >>> c.clear() # empty the counter
396n/a >>> c
397n/a Counter()
398n/a
399n/a Note: If a count is set to zero or reduced to zero, it will remain
400n/a in the counter until the entry is deleted or the counter is cleared:
401n/a
402n/a >>> c = Counter('aaabbc')
403n/a >>> c['b'] -= 2 # reduce the count of 'b' by two
404n/a >>> c.most_common() # 'b' is still in, but its count is zero
405n/a [('a', 3), ('c', 1), ('b', 0)]
406n/a
407n/a '''
408n/a # References:
409n/a # http://en.wikipedia.org/wiki/Multiset
410n/a # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
411n/a # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
412n/a # http://code.activestate.com/recipes/259174/
413n/a # Knuth, TAOCP Vol. II section 4.6.3
414n/a
415n/a def __init__(self, iterable=None, **kwds):
416n/a '''Create a new, empty Counter object. And if given, count elements
417n/a from an input iterable. Or, initialize the count from another mapping
418n/a of elements to their counts.
419n/a
420n/a >>> c = Counter() # a new, empty counter
421n/a >>> c = Counter('gallahad') # a new counter from an iterable
422n/a >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping
423n/a >>> c = Counter(a=4, b=2) # a new counter from keyword args
424n/a
425n/a '''
426n/a super().__init__()
427n/a self.update(iterable, **kwds)
428n/a
429n/a def __missing__(self, key):
430n/a 'The count of elements not in the Counter is zero.'
431n/a # Needed so that self[missing_item] does not raise KeyError
432n/a return 0
433n/a
434n/a def most_common(self, n=None):
435n/a '''List the n most common elements and their counts from the most
436n/a common to the least. If n is None, then list all element counts.
437n/a
438n/a >>> Counter('abcdeabcdabcaba').most_common(3)
439n/a [('a', 5), ('b', 4), ('c', 3)]
440n/a
441n/a '''
442n/a # Emulate Bag.sortedByCount from Smalltalk
443n/a if n is None:
444n/a return sorted(self.items(), key=_itemgetter(1), reverse=True)
445n/a return _heapq.nlargest(n, self.items(), key=_itemgetter(1))
446n/a
447n/a def elements(self):
448n/a '''Iterator over elements repeating each as many times as its count.
449n/a
450n/a >>> c = Counter('ABCABC')
451n/a >>> sorted(c.elements())
452n/a ['A', 'A', 'B', 'B', 'C', 'C']
453n/a
454n/a # Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
455n/a >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
456n/a >>> product = 1
457n/a >>> for factor in prime_factors.elements(): # loop over factors
458n/a ... product *= factor # and multiply them
459n/a >>> product
460n/a 1836
461n/a
462n/a Note, if an element's count has been set to zero or is a negative
463n/a number, elements() will ignore it.
464n/a
465n/a '''
466n/a # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
467n/a return _chain.from_iterable(_starmap(_repeat, self.items()))
468n/a
469n/a # Override dict methods where necessary
470n/a
471n/a @classmethod
472n/a def fromkeys(cls, iterable, v=None):
473n/a # There is no equivalent method for counters because setting v=1
474n/a # means that no element can have a count greater than one.
475n/a raise NotImplementedError(
476n/a 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
477n/a
478n/a def update(self, iterable=None, **kwds):
479n/a '''Like dict.update() but add counts instead of replacing them.
480n/a
481n/a Source can be an iterable, a dictionary, or another Counter instance.
482n/a
483n/a >>> c = Counter('which')
484n/a >>> c.update('witch') # add elements from another iterable
485n/a >>> d = Counter('watch')
486n/a >>> c.update(d) # add elements from another counter
487n/a >>> c['h'] # four 'h' in which, witch, and watch
488n/a 4
489n/a
490n/a '''
491n/a # The regular dict.update() operation makes no sense here because the
492n/a # replace behavior results in the some of original untouched counts
493n/a # being mixed-in with all of the other counts for a mismash that
494n/a # doesn't have a straight-forward interpretation in most counting
495n/a # contexts. Instead, we implement straight-addition. Both the inputs
496n/a # and outputs are allowed to contain zero and negative counts.
497n/a
498n/a if iterable is not None:
499n/a if isinstance(iterable, Mapping):
500n/a if self:
501n/a self_get = self.get
502n/a for elem, count in iterable.items():
503n/a self[elem] = count + self_get(elem, 0)
504n/a else:
505n/a super().update(iterable) # fast path when counter is empty
506n/a else:
507n/a _count_elements(self, iterable)
508n/a if kwds:
509n/a self.update(kwds)
510n/a
511n/a def subtract(self, iterable=None, **kwds):
512n/a '''Like dict.update() but subtracts counts instead of replacing them.
513n/a Counts can be reduced below zero. Both the inputs and outputs are
514n/a allowed to contain zero and negative counts.
515n/a
516n/a Source can be an iterable, a dictionary, or another Counter instance.
517n/a
518n/a >>> c = Counter('which')
519n/a >>> c.subtract('witch') # subtract elements from another iterable
520n/a >>> c.subtract(Counter('watch')) # subtract elements from another counter
521n/a >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch
522n/a 0
523n/a >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch
524n/a -1
525n/a
526n/a '''
527n/a if iterable is not None:
528n/a self_get = self.get
529n/a if isinstance(iterable, Mapping):
530n/a for elem, count in iterable.items():
531n/a self[elem] = self_get(elem, 0) - count
532n/a else:
533n/a for elem in iterable:
534n/a self[elem] = self_get(elem, 0) - 1
535n/a if kwds:
536n/a self.subtract(kwds)
537n/a
538n/a def copy(self):
539n/a 'Like dict.copy() but returns a Counter instance instead of a dict.'
540n/a return Counter(self)
541n/a
542n/a def __reduce__(self):
543n/a return self.__class__, (dict(self),)
544n/a
545n/a def __delitem__(self, elem):
546n/a 'Like dict.__delitem__() but does not raise KeyError for missing values.'
547n/a if elem in self:
548n/a super().__delitem__(elem)
549n/a
550n/a def __repr__(self):
551n/a if not self:
552n/a return '%s()' % self.__class__.__name__
553n/a items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
554n/a return '%s({%s})' % (self.__class__.__name__, items)
555n/a
556n/a # Multiset-style mathematical operations discussed in:
557n/a # Knuth TAOCP Volume II section 4.6.3 exercise 19
558n/a # and at http://en.wikipedia.org/wiki/Multiset
559n/a #
560n/a # Outputs guaranteed to only include positive counts.
561n/a #
562n/a # To strip negative and zero counts, add-in an empty counter:
563n/a # c += Counter()
564n/a
565n/a def __add__(self, other):
566n/a '''Add counts from two counters.
567n/a
568n/a >>> Counter('abbb') + Counter('bcc')
569n/a Counter({'b': 4, 'c': 2, 'a': 1})
570n/a
571n/a '''
572n/a if not isinstance(other, Counter):
573n/a return NotImplemented
574n/a result = Counter()
575n/a for elem in set(self) | set(other):
576n/a newcount = self[elem] + other[elem]
577n/a if newcount > 0:
578n/a result[elem] = newcount
579n/a return result
580n/a
581n/a def __sub__(self, other):
582n/a ''' Subtract count, but keep only results with positive counts.
583n/a
584n/a >>> Counter('abbbc') - Counter('bccd')
585n/a Counter({'b': 2, 'a': 1})
586n/a
587n/a '''
588n/a if not isinstance(other, Counter):
589n/a return NotImplemented
590n/a result = Counter()
591n/a for elem in set(self) | set(other):
592n/a newcount = self[elem] - other[elem]
593n/a if newcount > 0:
594n/a result[elem] = newcount
595n/a return result
596n/a
597n/a def __or__(self, other):
598n/a '''Union is the maximum of value in either of the input counters.
599n/a
600n/a >>> Counter('abbb') | Counter('bcc')
601n/a Counter({'b': 3, 'c': 2, 'a': 1})
602n/a
603n/a '''
604n/a if not isinstance(other, Counter):
605n/a return NotImplemented
606n/a result = Counter()
607n/a for elem in set(self) | set(other):
608n/a p, q = self[elem], other[elem]
609n/a newcount = q if p < q else p
610n/a if newcount > 0:
611n/a result[elem] = newcount
612n/a return result
613n/a
614n/a def __and__(self, other):
615n/a ''' Intersection is the minimum of corresponding counts.
616n/a
617n/a >>> Counter('abbb') & Counter('bcc')
618n/a Counter({'b': 1})
619n/a
620n/a '''
621n/a if not isinstance(other, Counter):
622n/a return NotImplemented
623n/a result = Counter()
624n/a if len(self) < len(other):
625n/a self, other = other, self
626n/a for elem in filter(self.__contains__, other):
627n/a p, q = self[elem], other[elem]
628n/a newcount = p if p < q else q
629n/a if newcount > 0:
630n/a result[elem] = newcount
631n/a return result
632n/a
633n/a
634n/a################################################################################
635n/a### UserDict
636n/a################################################################################
637n/a
638n/aclass UserDict(MutableMapping):
639n/a
640n/a # Start by filling-out the abstract methods
641n/a def __init__(self, dict=None, **kwargs):
642n/a self.data = {}
643n/a if dict is not None:
644n/a self.update(dict)
645n/a if len(kwargs):
646n/a self.update(kwargs)
647n/a def __len__(self): return len(self.data)
648n/a def __getitem__(self, key):
649n/a if key in self.data:
650n/a return self.data[key]
651n/a if hasattr(self.__class__, "__missing__"):
652n/a return self.__class__.__missing__(self, key)
653n/a raise KeyError(key)
654n/a def __setitem__(self, key, item): self.data[key] = item
655n/a def __delitem__(self, key): del self.data[key]
656n/a def __iter__(self):
657n/a return iter(self.data)
658n/a
659n/a # Modify __contains__ to work correctly when __missing__ is present
660n/a def __contains__(self, key):
661n/a return key in self.data
662n/a
663n/a # Now, add the methods in dicts but not in MutableMapping
664n/a def __repr__(self): return repr(self.data)
665n/a def copy(self):
666n/a if self.__class__ is UserDict:
667n/a return UserDict(self.data.copy())
668n/a import copy
669n/a data = self.data
670n/a try:
671n/a self.data = {}
672n/a c = copy.copy(self)
673n/a finally:
674n/a self.data = data
675n/a c.update(self)
676n/a return c
677n/a @classmethod
678n/a def fromkeys(cls, iterable, value=None):
679n/a d = cls()
680n/a for key in iterable:
681n/a d[key] = value
682n/a return d
683n/a
684n/a
685n/a
686n/a################################################################################
687n/a### UserList
688n/a################################################################################
689n/a
690n/aclass UserList(MutableSequence):
691n/a """A more or less complete user-defined wrapper around list objects."""
692n/a def __init__(self, initlist=None):
693n/a self.data = []
694n/a if initlist is not None:
695n/a # XXX should this accept an arbitrary sequence?
696n/a if type(initlist) == type(self.data):
697n/a self.data[:] = initlist
698n/a elif isinstance(initlist, UserList):
699n/a self.data[:] = initlist.data[:]
700n/a else:
701n/a self.data = list(initlist)
702n/a def __repr__(self): return repr(self.data)
703n/a def __lt__(self, other): return self.data < self.__cast(other)
704n/a def __le__(self, other): return self.data <= self.__cast(other)
705n/a def __eq__(self, other): return self.data == self.__cast(other)
706n/a def __ne__(self, other): return self.data != self.__cast(other)
707n/a def __gt__(self, other): return self.data > self.__cast(other)
708n/a def __ge__(self, other): return self.data >= self.__cast(other)
709n/a def __cast(self, other):
710n/a return other.data if isinstance(other, UserList) else other
711n/a def __contains__(self, item): return item in self.data
712n/a def __len__(self): return len(self.data)
713n/a def __getitem__(self, i): return self.data[i]
714n/a def __setitem__(self, i, item): self.data[i] = item
715n/a def __delitem__(self, i): del self.data[i]
716n/a def __add__(self, other):
717n/a if isinstance(other, UserList):
718n/a return self.__class__(self.data + other.data)
719n/a elif isinstance(other, type(self.data)):
720n/a return self.__class__(self.data + other)
721n/a return self.__class__(self.data + list(other))
722n/a def __radd__(self, other):
723n/a if isinstance(other, UserList):
724n/a return self.__class__(other.data + self.data)
725n/a elif isinstance(other, type(self.data)):
726n/a return self.__class__(other + self.data)
727n/a return self.__class__(list(other) + self.data)
728n/a def __iadd__(self, other):
729n/a if isinstance(other, UserList):
730n/a self.data += other.data
731n/a elif isinstance(other, type(self.data)):
732n/a self.data += other
733n/a else:
734n/a self.data += list(other)
735n/a return self
736n/a def __mul__(self, n):
737n/a return self.__class__(self.data*n)
738n/a __rmul__ = __mul__
739n/a def __imul__(self, n):
740n/a self.data *= n
741n/a return self
742n/a def append(self, item): self.data.append(item)
743n/a def insert(self, i, item): self.data.insert(i, item)
744n/a def pop(self, i=-1): return self.data.pop(i)
745n/a def remove(self, item): self.data.remove(item)
746n/a def count(self, item): return self.data.count(item)
747n/a def index(self, item, *args): return self.data.index(item, *args)
748n/a def reverse(self): self.data.reverse()
749n/a def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
750n/a def extend(self, other):
751n/a if isinstance(other, UserList):
752n/a self.data.extend(other.data)
753n/a else:
754n/a self.data.extend(other)
755n/a
756n/a
757n/a
758n/a################################################################################
759n/a### UserString
760n/a################################################################################
761n/a
762n/aclass UserString(Sequence):
763n/a def __init__(self, seq):
764n/a if isinstance(seq, str):
765n/a self.data = seq
766n/a elif isinstance(seq, UserString):
767n/a self.data = seq.data[:]
768n/a else:
769n/a self.data = str(seq)
770n/a def __str__(self): return str(self.data)
771n/a def __repr__(self): return repr(self.data)
772n/a def __int__(self): return int(self.data)
773n/a def __float__(self): return float(self.data)
774n/a def __complex__(self): return complex(self.data)
775n/a def __hash__(self): return hash(self.data)
776n/a
777n/a def __eq__(self, string):
778n/a if isinstance(string, UserString):
779n/a return self.data == string.data
780n/a return self.data == string
781n/a def __ne__(self, string):
782n/a if isinstance(string, UserString):
783n/a return self.data != string.data
784n/a return self.data != string
785n/a def __lt__(self, string):
786n/a if isinstance(string, UserString):
787n/a return self.data < string.data
788n/a return self.data < string
789n/a def __le__(self, string):
790n/a if isinstance(string, UserString):
791n/a return self.data <= string.data
792n/a return self.data <= string
793n/a def __gt__(self, string):
794n/a if isinstance(string, UserString):
795n/a return self.data > string.data
796n/a return self.data > string
797n/a def __ge__(self, string):
798n/a if isinstance(string, UserString):
799n/a return self.data >= string.data
800n/a return self.data >= string
801n/a
802n/a def __contains__(self, char):
803n/a if isinstance(char, UserString):
804n/a char = char.data
805n/a return char in self.data
806n/a
807n/a def __len__(self): return len(self.data)
808n/a def __getitem__(self, index): return self.__class__(self.data[index])
809n/a def __add__(self, other):
810n/a if isinstance(other, UserString):
811n/a return self.__class__(self.data + other.data)
812n/a elif isinstance(other, str):
813n/a return self.__class__(self.data + other)
814n/a return self.__class__(self.data + str(other))
815n/a def __radd__(self, other):
816n/a if isinstance(other, str):
817n/a return self.__class__(other + self.data)
818n/a return self.__class__(str(other) + self.data)
819n/a def __mul__(self, n):
820n/a return self.__class__(self.data*n)
821n/a __rmul__ = __mul__
822n/a def __mod__(self, args):
823n/a return self.__class__(self.data % args)
824n/a
825n/a # the following methods are defined in alphabetical order:
826n/a def capitalize(self): return self.__class__(self.data.capitalize())
827n/a def center(self, width, *args):
828n/a return self.__class__(self.data.center(width, *args))
829n/a def count(self, sub, start=0, end=_sys.maxsize):
830n/a if isinstance(sub, UserString):
831n/a sub = sub.data
832n/a return self.data.count(sub, start, end)
833n/a def encode(self, encoding=None, errors=None): # XXX improve this?
834n/a if encoding:
835n/a if errors:
836n/a return self.__class__(self.data.encode(encoding, errors))
837n/a return self.__class__(self.data.encode(encoding))
838n/a return self.__class__(self.data.encode())
839n/a def endswith(self, suffix, start=0, end=_sys.maxsize):
840n/a return self.data.endswith(suffix, start, end)
841n/a def expandtabs(self, tabsize=8):
842n/a return self.__class__(self.data.expandtabs(tabsize))
843n/a def find(self, sub, start=0, end=_sys.maxsize):
844n/a if isinstance(sub, UserString):
845n/a sub = sub.data
846n/a return self.data.find(sub, start, end)
847n/a def format(self, *args, **kwds):
848n/a return self.data.format(*args, **kwds)
849n/a def index(self, sub, start=0, end=_sys.maxsize):
850n/a return self.data.index(sub, start, end)
851n/a def isalpha(self): return self.data.isalpha()
852n/a def isalnum(self): return self.data.isalnum()
853n/a def isdecimal(self): return self.data.isdecimal()
854n/a def isdigit(self): return self.data.isdigit()
855n/a def isidentifier(self): return self.data.isidentifier()
856n/a def islower(self): return self.data.islower()
857n/a def isnumeric(self): return self.data.isnumeric()
858n/a def isspace(self): return self.data.isspace()
859n/a def istitle(self): return self.data.istitle()
860n/a def isupper(self): return self.data.isupper()
861n/a def join(self, seq): return self.data.join(seq)
862n/a def ljust(self, width, *args):
863n/a return self.__class__(self.data.ljust(width, *args))
864n/a def lower(self): return self.__class__(self.data.lower())
865n/a def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
866n/a def partition(self, sep):
867n/a return self.data.partition(sep)
868n/a def replace(self, old, new, maxsplit=-1):
869n/a if isinstance(old, UserString):
870n/a old = old.data
871n/a if isinstance(new, UserString):
872n/a new = new.data
873n/a return self.__class__(self.data.replace(old, new, maxsplit))
874n/a def rfind(self, sub, start=0, end=_sys.maxsize):
875n/a if isinstance(sub, UserString):
876n/a sub = sub.data
877n/a return self.data.rfind(sub, start, end)
878n/a def rindex(self, sub, start=0, end=_sys.maxsize):
879n/a return self.data.rindex(sub, start, end)
880n/a def rjust(self, width, *args):
881n/a return self.__class__(self.data.rjust(width, *args))
882n/a def rpartition(self, sep):
883n/a return self.data.rpartition(sep)
884n/a def rstrip(self, chars=None):
885n/a return self.__class__(self.data.rstrip(chars))
886n/a def split(self, sep=None, maxsplit=-1):
887n/a return self.data.split(sep, maxsplit)
888n/a def rsplit(self, sep=None, maxsplit=-1):
889n/a return self.data.rsplit(sep, maxsplit)
890n/a def splitlines(self, keepends=0): return self.data.splitlines(keepends)
891n/a def startswith(self, prefix, start=0, end=_sys.maxsize):
892n/a return self.data.startswith(prefix, start, end)
893n/a def strip(self, chars=None): return self.__class__(self.data.strip(chars))
894n/a def swapcase(self): return self.__class__(self.data.swapcase())
895n/a def title(self): return self.__class__(self.data.title())
896n/a def translate(self, *args):
897n/a return self.__class__(self.data.translate(*args))
898n/a def upper(self): return self.__class__(self.data.upper())
899n/a def zfill(self, width): return self.__class__(self.data.zfill(width))
900n/a
901n/a
902n/a
903n/a################################################################################
904n/a### Simple tests
905n/a################################################################################
906n/a
907n/aif __name__ == '__main__':
908n/a # verify that instances can be pickled
909n/a from pickle import loads, dumps
910n/a Point = namedtuple('Point', 'x, y', True)
911n/a p = Point(x=10, y=20)
912n/a assert p == loads(dumps(p))
913n/a
914n/a # test and demonstrate ability to override methods
915n/a class Point(namedtuple('Point', 'x y')):
916n/a __slots__ = ()
917n/a @property
918n/a def hypot(self):
919n/a return (self.x ** 2 + self.y ** 2) ** 0.5
920n/a def __str__(self):
921n/a return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
922n/a
923n/a for p in Point(3, 4), Point(14, 5/7.):
924n/a print (p)
925n/a
926n/a class Point(namedtuple('Point', 'x y')):
927n/a 'Point class with optimized _make() and _replace() without error-checking'
928n/a __slots__ = ()
929n/a _make = classmethod(tuple.__new__)
930n/a def _replace(self, _map=map, **kwds):
931n/a return self._make(_map(kwds.get, ('x', 'y'), self))
932n/a
933n/a print(Point(11, 22)._replace(x=100))
934n/a
935n/a Point3D = namedtuple('Point3D', Point._fields + ('z',))
936n/a print(Point3D.__doc__)
937n/a
938n/a import doctest
939n/a TestResults = namedtuple('TestResults', 'failed attempted')
940n/a print(TestResults(*doctest.testmod()))