python之旅3

1 collections系列

方法如下

  1 class Counter(dict):
  2     ‘‘‘Dict subclass for counting hashable items.  Sometimes called a bag
  3     or multiset.  Elements are stored as dictionary keys and their counts
  4     are stored as dictionary values.
  5
  6     >>> c = Counter(‘abcdeabcdabcaba‘)  # count elements from a string
  7
  8     >>> c.most_common(3)                # three most common elements
  9     [(‘a‘, 5), (‘b‘, 4), (‘c‘, 3)]
 10     >>> sorted(c)                       # list all unique elements
 11     [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]
 12     >>> ‘‘.join(sorted(c.elements()))   # list elements with repetitions
 13     ‘aaaaabbbbcccdde‘
 14     >>> sum(c.values())                 # total of all counts
 15     15
 16
 17     >>> c[‘a‘]                          # count of letter ‘a‘
 18     5
 19     >>> for elem in ‘shazam‘:           # update counts from an iterable
 20     ...     c[elem] += 1                # by adding 1 to each element‘s count
 21     >>> c[‘a‘]                          # now there are seven ‘a‘
 22     7
 23     >>> del c[‘b‘]                      # remove all ‘b‘
 24     >>> c[‘b‘]                          # now there are zero ‘b‘
 25     0
 26
 27     >>> d = Counter(‘simsalabim‘)       # make another counter
 28     >>> c.update(d)                     # add in the second counter
 29     >>> c[‘a‘]                          # now there are nine ‘a‘
 30     9
 31
 32     >>> c.clear()                       # empty the counter
 33     >>> c
 34     Counter()
 35
 36     Note:  If a count is set to zero or reduced to zero, it will remain
 37     in the counter until the entry is deleted or the counter is cleared:
 38
 39     >>> c = Counter(‘aaabbc‘)
 40     >>> c[‘b‘] -= 2                     # reduce the count of ‘b‘ by two
 41     >>> c.most_common()                 # ‘b‘ is still in, but its count is zero
 42     [(‘a‘, 3), (‘c‘, 1), (‘b‘, 0)]
 43
 44     ‘‘‘
 45     # References:
 46     #   http://en.wikipedia.org/wiki/Multiset
 47     #   http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
 48     #   http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
 49     #   http://code.activestate.com/recipes/259174/
 50     #   Knuth, TAOCP Vol. II section 4.6.3
 51
 52     def __init__(*args, **kwds):
 53         ‘‘‘Create a new, empty Counter object.  And if given, count elements
 54         from an input iterable.  Or, initialize the count from another mapping
 55         of elements to their counts.
 56
 57         >>> c = Counter()                           # a new, empty counter
 58         >>> c = Counter(‘gallahad‘)                 # a new counter from an iterable
 59         >>> c = Counter({‘a‘: 4, ‘b‘: 2})           # a new counter from a mapping
 60         >>> c = Counter(a=4, b=2)                   # a new counter from keyword args
 61
 62         ‘‘‘
 63         if not args:
 64             raise TypeError("descriptor ‘__init__‘ of ‘Counter‘ object "
 65                             "needs an argument")
 66         self = args[0]
 67         args = args[1:]
 68         if len(args) > 1:
 69             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
 70         super(Counter, self).__init__()
 71         self.update(*args, **kwds)
 72
 73     def __missing__(self, key):
 74         ‘The count of elements not in the Counter is zero.‘
 75         # Needed so that self[missing_item] does not raise KeyError
 76         return 0
 77
 78     def most_common(self, n=None):
 79         ‘‘‘List the n most common elements and their counts from the most
 80         common to the least.  If n is None, then list all element counts.
 81
 82         >>> Counter(‘abcdeabcdabcaba‘).most_common(3)
 83         [(‘a‘, 5), (‘b‘, 4), (‘c‘, 3)]
 84
 85         ‘‘‘
 86         # Emulate Bag.sortedByCount from Smalltalk
 87         if n is None:
 88             return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
 89         return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1))
 90
 91     def elements(self):
 92         ‘‘‘Iterator over elements repeating each as many times as its count.
 93
 94         >>> c = Counter(‘ABCABC‘)
 95         >>> sorted(c.elements())
 96         [‘A‘, ‘A‘, ‘B‘, ‘B‘, ‘C‘, ‘C‘]
 97
 98         # Knuth‘s example for prime factors of 1836:  2**2 * 3**3 * 17**1
 99         >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
100         >>> product = 1
101         >>> for factor in prime_factors.elements():     # loop over factors
102         ...     product *= factor                       # and multiply them
103         >>> product
104         1836
105
106         Note, if an element‘s count has been set to zero or is a negative
107         number, elements() will ignore it.
108
109         ‘‘‘
110         # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
111         return _chain.from_iterable(_starmap(_repeat, self.iteritems()))
112
113     # Override dict methods where necessary
114
115     @classmethod
116     def fromkeys(cls, iterable, v=None):
117         # There is no equivalent method for counters because setting v=1
118         # means that no element can have a count greater than one.
119         raise NotImplementedError(
120             ‘Counter.fromkeys() is undefined.  Use Counter(iterable) instead.‘)
121
122     def update(*args, **kwds):
123         ‘‘‘Like dict.update() but add counts instead of replacing them.
124
125         Source can be an iterable, a dictionary, or another Counter instance.
126
127         >>> c = Counter(‘which‘)
128         >>> c.update(‘witch‘)           # add elements from another iterable
129         >>> d = Counter(‘watch‘)
130         >>> c.update(d)                 # add elements from another counter
131         >>> c[‘h‘]                      # four ‘h‘ in which, witch, and watch
132         4
133
134         ‘‘‘
135         # The regular dict.update() operation makes no sense here because the
136         # replace behavior results in the some of original untouched counts
137         # being mixed-in with all of the other counts for a mismash that
138         # doesn‘t have a straight-forward interpretation in most counting
139         # contexts.  Instead, we implement straight-addition.  Both the inputs
140         # and outputs are allowed to contain zero and negative counts.
141
142         if not args:
143             raise TypeError("descriptor ‘update‘ of ‘Counter‘ object "
144                             "needs an argument")
145         self = args[0]
146         args = args[1:]
147         if len(args) > 1:
148             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
149         iterable = args[0] if args else None
150         if iterable is not None:
151             if isinstance(iterable, Mapping):
152                 if self:
153                     self_get = self.get
154                     for elem, count in iterable.iteritems():
155                         self[elem] = self_get(elem, 0) + count
156                 else:
157                     super(Counter, self).update(iterable) # fast path when counter is empty
158             else:
159                 self_get = self.get
160                 for elem in iterable:
161                     self[elem] = self_get(elem, 0) + 1
162         if kwds:
163             self.update(kwds)
164
165     def subtract(*args, **kwds):
166         ‘‘‘Like dict.update() but subtracts counts instead of replacing them.
167         Counts can be reduced below zero.  Both the inputs and outputs are
168         allowed to contain zero and negative counts.
169
170         Source can be an iterable, a dictionary, or another Counter instance.
171
172         >>> c = Counter(‘which‘)
173         >>> c.subtract(‘witch‘)             # subtract elements from another iterable
174         >>> c.subtract(Counter(‘watch‘))    # subtract elements from another counter
175         >>> c[‘h‘]                          # 2 in which, minus 1 in witch, minus 1 in watch
176         0
177         >>> c[‘w‘]                          # 1 in which, minus 1 in witch, minus 1 in watch
178         -1
179
180         ‘‘‘
181         if not args:
182             raise TypeError("descriptor ‘subtract‘ of ‘Counter‘ object "
183                             "needs an argument")
184         self = args[0]
185         args = args[1:]
186         if len(args) > 1:
187             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
188         iterable = args[0] if args else None
189         if iterable is not None:
190             self_get = self.get
191             if isinstance(iterable, Mapping):
192                 for elem, count in iterable.items():
193                     self[elem] = self_get(elem, 0) - count
194             else:
195                 for elem in iterable:
196                     self[elem] = self_get(elem, 0) - 1
197         if kwds:
198             self.subtract(kwds)
199
200     def copy(self):
201         ‘Return a shallow copy.‘
202         return self.__class__(self)
203
204     def __reduce__(self):
205         return self.__class__, (dict(self),)
206
207     def __delitem__(self, elem):
208         ‘Like dict.__delitem__() but does not raise KeyError for missing values.‘
209         if elem in self:
210             super(Counter, self).__delitem__(elem)
211
212     def __repr__(self):
213         if not self:
214             return ‘%s()‘ % self.__class__.__name__
215         items = ‘, ‘.join(map(‘%r: %r‘.__mod__, self.most_common()))
216         return ‘%s({%s})‘ % (self.__class__.__name__, items)
217
218     # Multiset-style mathematical operations discussed in:
219     #       Knuth TAOCP Volume II section 4.6.3 exercise 19
220     #       and at http://en.wikipedia.org/wiki/Multiset
221     #
222     # Outputs guaranteed to only include positive counts.
223     #
224     # To strip negative and zero counts, add-in an empty counter:
225     #       c += Counter()
226
227     def __add__(self, other):
228         ‘‘‘Add counts from two counters.
229
230         >>> Counter(‘abbb‘) + Counter(‘bcc‘)
231         Counter({‘b‘: 4, ‘c‘: 2, ‘a‘: 1})
232
233         ‘‘‘
234         if not isinstance(other, Counter):
235             return NotImplemented
236         result = Counter()
237         for elem, count in self.items():
238             newcount = count + other[elem]
239             if newcount > 0:
240                 result[elem] = newcount
241         for elem, count in other.items():
242             if elem not in self and count > 0:
243                 result[elem] = count
244         return result
245
246     def __sub__(self, other):
247         ‘‘‘ Subtract count, but keep only results with positive counts.
248
249         >>> Counter(‘abbbc‘) - Counter(‘bccd‘)
250         Counter({‘b‘: 2, ‘a‘: 1})
251
252         ‘‘‘
253         if not isinstance(other, Counter):
254             return NotImplemented
255         result = Counter()
256         for elem, count in self.items():
257             newcount = count - other[elem]
258             if newcount > 0:
259                 result[elem] = newcount
260         for elem, count in other.items():
261             if elem not in self and count < 0:
262                 result[elem] = 0 - count
263         return result
264
265     def __or__(self, other):
266         ‘‘‘Union is the maximum of value in either of the input counters.
267
268         >>> Counter(‘abbb‘) | Counter(‘bcc‘)
269         Counter({‘b‘: 3, ‘c‘: 2, ‘a‘: 1})
270
271         ‘‘‘
272         if not isinstance(other, Counter):
273             return NotImplemented
274         result = Counter()
275         for elem, count in self.items():
276             other_count = other[elem]
277             newcount = other_count if count < other_count else count
278             if newcount > 0:
279                 result[elem] = newcount
280         for elem, count in other.items():
281             if elem not in self and count > 0:
282                 result[elem] = count
283         return result
284
285     def __and__(self, other):
286         ‘‘‘ Intersection is the minimum of corresponding counts.
287
288         >>> Counter(‘abbb‘) & Counter(‘bcc‘)
289         Counter({‘b‘: 1})
290
291         ‘‘‘
292         if not isinstance(other, Counter):
293             return NotImplemented
294         result = Counter()
295         for elem, count in self.items():
296             other_count = other[elem]
297             newcount = count if count < other_count else other_count
298             if newcount > 0:
299                 result[elem] = newcount
300         return result
301
302
303 if __name__ == ‘__main__‘:
304     # verify that instances can be pickled
305     from cPickle import loads, dumps
306     Point = namedtuple(‘Point‘, ‘x, y‘, True)
307     p = Point(x=10, y=20)
308     assert p == loads(dumps(p))
309
310     # test and demonstrate ability to override methods
311     class Point(namedtuple(‘Point‘, ‘x y‘)):
312         __slots__ = ()
313         @property
314         def hypot(self):
315             return (self.x ** 2 + self.y ** 2) ** 0.5
316         def __str__(self):
317             return ‘Point: x=%6.3f  y=%6.3f  hypot=%6.3f‘ % (self.x, self.y, self.hypot)
318
319     for p in Point(3, 4), Point(14, 5/7.):
320         print p
321
322     class Point(namedtuple(‘Point‘, ‘x y‘)):
323         ‘Point class with optimized _make() and _replace() without error-checking‘
324         __slots__ = ()
325         _make = classmethod(tuple.__new__)
326         def _replace(self, _map=map, **kwds):
327             return self._make(_map(kwds.get, (‘x‘, ‘y‘), self))
328
329     print Point(11, 22)._replace(x=100)
330
331     Point3D = namedtuple(‘Point3D‘, Point._fields + (‘z‘,))
332     print Point3D.__doc__
333
334     import doctest
335     TestResults = namedtuple(‘TestResults‘, ‘failed attempted‘)
336     print TestResults(*doctest.testmod())

常用方法如下:
1,计数器

 1 >>> import collections
 2 >>> c1 = collections.Counter(‘aabbccddww‘)
 3 >>> c1
 4 Counter({‘a‘: 2, ‘c‘: 2, ‘b‘: 2, ‘d‘: 2, ‘w‘: 2})
 5 >>> c1.most_common(3)  取出前三个
 6 [(‘a‘, 2), (‘c‘, 2), (‘b‘, 2)]
 7 >>> c2 = collections.Counter(‘aabbttyy‘)
 8 >>> c2
 9 Counter({‘a‘: 2, ‘y‘: 2, ‘b‘: 2, ‘t‘: 2})
10 >>> c1.update(c2)  合并,c2的元素合并到了c1
11 >>> c1
12 Counter({‘a‘: 4, ‘b‘: 4, ‘c‘: 2, ‘d‘: 2, ‘t‘: 2, ‘w‘: 2, ‘y‘:
13
14 2})
15 >>> c1[‘a‘]       取出计数器中的元素,没有返回0
16 4
17 >>> c1[‘g‘]
18 0
19 >>> c2.clear()  清除
20 >>> c1.elements()  返回一个迭代器
21 <itertools.chain object at 0x015A63F0>
22 >>> for item in c1.elements():
23 ...     print item
24 ...
25 a
26 a
27 a
28 a
29 c
30 c
31 b
32 b
33 b
34 b
35 d
36 d
37 t
38 t
39 w
40 w
41 y
42 y

2 有序字典
方法如下

  1 class OrderedDict(dict):
  2     ‘Dictionary that remembers insertion order‘
  3     # An inherited dict maps keys to values.
  4     # The inherited dict provides __getitem__, __len__, __contains__, and get.
  5     # The remaining methods are order-aware.
  6     # Big-O running times for all methods are the same as regular dictionaries.
  7
  8     # The internal self.__map dict maps keys to links in a doubly linked list.
  9     # The circular doubly linked list starts and ends with a sentinel element.
 10     # The sentinel element never gets deleted (this simplifies the algorithm).
 11     # Each link is stored as a list of length three:  [PREV, NEXT, KEY].
 12
 13     def __init__(*args, **kwds):
 14         ‘‘‘Initialize an ordered dictionary.  The signature is the same as
 15         regular dictionaries, but keyword arguments are not recommended because
 16         their insertion order is arbitrary.
 17
 18         ‘‘‘
 19         if not args:
 20             raise TypeError("descriptor ‘__init__‘ of ‘OrderedDict‘ object "
 21                             "needs an argument")
 22         self = args[0]
 23         args = args[1:]
 24         if len(args) > 1:
 25             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
 26         try:
 27             self.__root
 28         except AttributeError:
 29             self.__root = root = []                     # sentinel node
 30             root[:] = [root, root, None]
 31             self.__map = {}
 32         self.__update(*args, **kwds)
 33
 34     def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
 35         ‘od.__setitem__(i, y) <==> od[i]=y‘
 36         # Setting a new item creates a new link at the end of the linked list,
 37         # and the inherited dictionary is updated with the new key/value pair.
 38         if key not in self:
 39             root = self.__root
 40             last = root[0]
 41             last[1] = root[0] = self.__map[key] = [last, root, key]
 42         return dict_setitem(self, key, value)
 43
 44     def __delitem__(self, key, dict_delitem=dict.__delitem__):
 45         ‘od.__delitem__(y) <==> del od[y]‘
 46         # Deleting an existing item uses self.__map to find the link which gets
 47         # removed by updating the links in the predecessor and successor nodes.
 48         dict_delitem(self, key)
 49         link_prev, link_next, _ = self.__map.pop(key)
 50         link_prev[1] = link_next                        # update link_prev[NEXT]
 51         link_next[0] = link_prev                        # update link_next[PREV]
 52
 53     def __iter__(self):
 54         ‘od.__iter__() <==> iter(od)‘
 55         # Traverse the linked list in order.
 56         root = self.__root
 57         curr = root[1]                                  # start at the first node
 58         while curr is not root:
 59             yield curr[2]                               # yield the curr[KEY]
 60             curr = curr[1]                              # move to next node
 61
 62     def __reversed__(self):
 63         ‘od.__reversed__() <==> reversed(od)‘
 64         # Traverse the linked list in reverse order.
 65         root = self.__root
 66         curr = root[0]                                  # start at the last node
 67         while curr is not root:
 68             yield curr[2]                               # yield the curr[KEY]
 69             curr = curr[0]                              # move to previous node
 70
 71     def clear(self):
 72         ‘od.clear() -> None.  Remove all items from od.‘
 73         root = self.__root
 74         root[:] = [root, root, None]
 75         self.__map.clear()
 76         dict.clear(self)
 77
 78     # -- the following methods do not depend on the internal structure --
 79
 80     def keys(self):
 81         ‘od.keys() -> list of keys in od‘
 82         return list(self)
 83
 84     def values(self):
 85         ‘od.values() -> list of values in od‘
 86         return [self[key] for key in self]
 87
 88     def items(self):
 89         ‘od.items() -> list of (key, value) pairs in od‘
 90         return [(key, self[key]) for key in self]
 91
 92     def iterkeys(self):
 93         ‘od.iterkeys() -> an iterator over the keys in od‘
 94         return iter(self)
 95
 96     def itervalues(self):
 97         ‘od.itervalues -> an iterator over the values in od‘
 98         for k in self:
 99             yield self[k]
100
101     def iteritems(self):
102         ‘od.iteritems -> an iterator over the (key, value) pairs in od‘
103         for k in self:
104             yield (k, self[k])
105
106     update = MutableMapping.update
107
108     __update = update # let subclasses override update without breaking __init__
109
110     __marker = object()
111
112     def pop(self, key, default=__marker):
113         ‘‘‘od.pop(k[,d]) -> v, remove specified key and return the corresponding
114         value.  If key is not found, d is returned if given, otherwise KeyError
115         is raised.
116
117         ‘‘‘
118         if key in self:
119             result = self[key]
120             del self[key]
121             return result
122         if default is self.__marker:
123             raise KeyError(key)
124         return default
125
126     def setdefault(self, key, default=None):
127         ‘od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od‘
128         if key in self:
129             return self[key]
130         self[key] = default
131         return default
132
133     def popitem(self, last=True):
134         ‘‘‘od.popitem() -> (k, v), return and remove a (key, value) pair.
135         Pairs are returned in LIFO order if last is true or FIFO order if false.
136
137         ‘‘‘
138         if not self:
139             raise KeyError(‘dictionary is empty‘)
140         key = next(reversed(self) if last else iter(self))
141         value = self.pop(key)
142         return key, value
143
144     def __repr__(self, _repr_running={}):
145         ‘od.__repr__() <==> repr(od)‘
146         call_key = id(self), _get_ident()
147         if call_key in _repr_running:
148             return ‘...‘
149         _repr_running[call_key] = 1
150         try:
151             if not self:
152                 return ‘%s()‘ % (self.__class__.__name__,)
153             return ‘%s(%r)‘ % (self.__class__.__name__, self.items())
154         finally:
155             del _repr_running[call_key]
156
157     def __reduce__(self):
158         ‘Return state information for pickling‘
159         items = [[k, self[k]] for k in self]
160         inst_dict = vars(self).copy()
161         for k in vars(OrderedDict()):
162             inst_dict.pop(k, None)
163         if inst_dict:
164             return (self.__class__, (items,), inst_dict)
165         return self.__class__, (items,)
166
167     def copy(self):
168         ‘od.copy() -> a shallow copy of od‘
169         return self.__class__(self)
170
171     @classmethod
172     def fromkeys(cls, iterable, value=None):
173         ‘‘‘OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
174         If not specified, the value defaults to None.
175
176         ‘‘‘
177         self = cls()
178         for key in iterable:
179             self[key] = value
180         return self
181
182     def __eq__(self, other):
183         ‘‘‘od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
184         while comparison to a regular mapping is order-insensitive.
185
186         ‘‘‘
187         if isinstance(other, OrderedDict):
188             return dict.__eq__(self, other) and all(_imap(_eq, self, other))
189         return dict.__eq__(self, other)
190
191     def __ne__(self, other):
192         ‘od.__ne__(y) <==> od!=y‘
193         return not self == other
194
195     # -- the following methods support python 3.x style dictionary views --
196
197     def viewkeys(self):
198         "od.viewkeys() -> a set-like object providing a view on od‘s keys"
199         return KeysView(self)
200
201     def viewvalues(self):
202         "od.viewvalues() -> an object providing a view on od‘s values"
203         return ValuesView(self)
204
205     def viewitems(self):
206         "od.viewitems() -> a set-like object providing a view on od‘s items"
207         return ItemsView(self)
208
209
210 ################################################################################
211 ### namedtuple
212 ################################################################################
213
214 _class_template = ‘‘‘215 class {typename}(tuple):
216     ‘{typename}({arg_list})‘
217
218     __slots__ = ()
219
220     _fields = {field_names!r}
221
222     def __new__(_cls, {arg_list}):
223         ‘Create new instance of {typename}({arg_list})‘
224         return _tuple.__new__(_cls, ({arg_list}))
225
226     @classmethod
227     def _make(cls, iterable, new=tuple.__new__, len=len):
228         ‘Make a new {typename} object from a sequence or iterable‘
229         result = new(cls, iterable)
230         if len(result) != {num_fields:d}:
231             raise TypeError(‘Expected {num_fields:d} arguments, got %d‘ % len(result))
232         return result
233
234     def __repr__(self):
235         ‘Return a nicely formatted representation string‘
236         return ‘{typename}({repr_fmt})‘ % self
237
238     def _asdict(self):
239         ‘Return a new OrderedDict which maps field names to their values‘
240         return OrderedDict(zip(self._fields, self))
241
242     def _replace(_self, **kwds):
243         ‘Return a new {typename} object replacing specified fields with new values‘
244         result = _self._make(map(kwds.pop, {field_names!r}, _self))
245         if kwds:
246             raise ValueError(‘Got unexpected field names: %r‘ % kwds.keys())
247         return result
248
249     def __getnewargs__(self):
250         ‘Return self as a plain tuple.  Used by copy and pickle.‘
251         return tuple(self)
252
253     __dict__ = _property(_asdict)
254
255     def __getstate__(self):
256         ‘Exclude the OrderedDict from pickling‘
257         pass
258
259 {field_defs}
260 ‘‘‘
261
262 _repr_template = ‘{name}=%r‘
263
264 _field_template = ‘‘‘265     {name} = _property(_itemgetter({index:d}), doc=‘Alias for field number {index:d}‘)
266 ‘‘‘
267
268 def namedtuple(typename, field_names, verbose=False, rename=False):
269     """Returns a new subclass of tuple with named fields.
270
271     >>> Point = namedtuple(‘Point‘, [‘x‘, ‘y‘])
272     >>> Point.__doc__                   # docstring for the new class
273     ‘Point(x, y)‘
274     >>> p = Point(11, y=22)             # instantiate with positional args or keywords
275     >>> p[0] + p[1]                     # indexable like a plain tuple
276     33
277     >>> x, y = p                        # unpack like a regular tuple
278     >>> x, y
279     (11, 22)
280     >>> p.x + p.y                       # fields also accessable by name
281     33
282     >>> d = p._asdict()                 # convert to a dictionary
283     >>> d[‘x‘]
284     11
285     >>> Point(**d)                      # convert from a dictionary
286     Point(x=11, y=22)
287     >>> p._replace(x=100)               # _replace() is like str.replace() but targets named fields
288     Point(x=100, y=22)
289
290     """
291
292     # Validate the field names.  At the user‘s option, either generate an error
293     # message or automatically replace the field name with a valid name.
294     if isinstance(field_names, basestring):
295         field_names = field_names.replace(‘,‘, ‘ ‘).split()
296     field_names = map(str, field_names)
297     typename = str(typename)
298     if rename:
299         seen = set()
300         for index, name in enumerate(field_names):
301             if (not all(c.isalnum() or c==‘_‘ for c in name)
302                 or _iskeyword(name)
303                 or not name
304                 or name[0].isdigit()
305                 or name.startswith(‘_‘)
306                 or name in seen):
307                 field_names[index] = ‘_%d‘ % index
308             seen.add(name)
309     for name in [typename] + field_names:
310         if type(name) != str:
311             raise TypeError(‘Type names and field names must be strings‘)
312         if not all(c.isalnum() or c==‘_‘ for c in name):
313             raise ValueError(‘Type names and field names can only contain ‘
314                              ‘alphanumeric characters and underscores: %r‘ % name)
315         if _iskeyword(name):
316             raise ValueError(‘Type names and field names cannot be a ‘
317                              ‘keyword: %r‘ % name)
318         if name[0].isdigit():
319             raise ValueError(‘Type names and field names cannot start with ‘
320                              ‘a number: %r‘ % name)
321     seen = set()
322     for name in field_names:
323         if name.startswith(‘_‘) and not rename:
324             raise ValueError(‘Field names cannot start with an underscore: ‘
325                              ‘%r‘ % name)
326         if name in seen:
327             raise ValueError(‘Encountered duplicate field name: %r‘ % name)
328         seen.add(name)
329
330     # Fill-in the class template
331     class_definition = _class_template.format(
332         typename = typename,
333         field_names = tuple(field_names),
334         num_fields = len(field_names),
335         arg_list = repr(tuple(field_names)).replace("‘", "")[1:-1],
336         repr_fmt = ‘, ‘.join(_repr_template.format(name=name)
337                              for name in field_names),
338         field_defs = ‘\n‘.join(_field_template.format(index=index, name=name)
339                                for index, name in enumerate(field_names))
340     )
341     if verbose:
342         print class_definition
343
344     # Execute the template string in a temporary namespace and support
345     # tracing utilities by setting a value for frame.f_globals[‘__name__‘]
346     namespace = dict(_itemgetter=_itemgetter, __name__=‘namedtuple_%s‘ % typename,
347                      OrderedDict=OrderedDict, _property=property, _tuple=tuple)
348     try:
349         exec class_definition in namespace
350     except SyntaxError as e:
351         raise SyntaxError(e.message + ‘:\n‘ + class_definition)
352     result = namespace[typename]
353
354     # For pickling to work, the __module__ variable needs to be set to the frame
355     # where the named tuple is created.  Bypass this step in environments where
356     # sys._getframe is not defined (Jython for example) or sys._getframe is not
357     # defined for arguments greater than 0 (IronPython).
358     try:
359         result.__module__ = _sys._getframe(1).f_globals.get(‘__name__‘, ‘__main__‘)
360     except (AttributeError, ValueError):
361         pass
362
363     return result
364
365
366 ########################################################################
367 ###  Counter
368 ########################################################################
369
370 class Counter(dict):
371     ‘‘‘Dict subclass for counting hashable items.  Sometimes called a bag
372     or multiset.  Elements are stored as dictionary keys and their counts
373     are stored as dictionary values.
374
375     >>> c = Counter(‘abcdeabcdabcaba‘)  # count elements from a string
376
377     >>> c.most_common(3)                # three most common elements
378     [(‘a‘, 5), (‘b‘, 4), (‘c‘, 3)]
379     >>> sorted(c)                       # list all unique elements
380     [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]
381     >>> ‘‘.join(sorted(c.elements()))   # list elements with repetitions
382     ‘aaaaabbbbcccdde‘
383     >>> sum(c.values())                 # total of all counts
384     15
385
386     >>> c[‘a‘]                          # count of letter ‘a‘
387     5
388     >>> for elem in ‘shazam‘:           # update counts from an iterable
389     ...     c[elem] += 1                # by adding 1 to each element‘s count
390     >>> c[‘a‘]                          # now there are seven ‘a‘
391     7
392     >>> del c[‘b‘]                      # remove all ‘b‘
393     >>> c[‘b‘]                          # now there are zero ‘b‘
394     0
395
396     >>> d = Counter(‘simsalabim‘)       # make another counter
397     >>> c.update(d)                     # add in the second counter
398     >>> c[‘a‘]                          # now there are nine ‘a‘
399     9
400
401     >>> c.clear()                       # empty the counter
402     >>> c
403     Counter()
404
405     Note:  If a count is set to zero or reduced to zero, it will remain
406     in the counter until the entry is deleted or the counter is cleared:
407
408     >>> c = Counter(‘aaabbc‘)
409     >>> c[‘b‘] -= 2                     # reduce the count of ‘b‘ by two
410     >>> c.most_common()                 # ‘b‘ is still in, but its count is zero
411     [(‘a‘, 3), (‘c‘, 1), (‘b‘, 0)]
412
413     ‘‘‘
414     # References:
415     #   http://en.wikipedia.org/wiki/Multiset
416     #   http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html
417     #   http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm
418     #   http://code.activestate.com/recipes/259174/
419     #   Knuth, TAOCP Vol. II section 4.6.3
420
421     def __init__(*args, **kwds):
422         ‘‘‘Create a new, empty Counter object.  And if given, count elements
423         from an input iterable.  Or, initialize the count from another mapping
424         of elements to their counts.
425
426         >>> c = Counter()                           # a new, empty counter
427         >>> c = Counter(‘gallahad‘)                 # a new counter from an iterable
428         >>> c = Counter({‘a‘: 4, ‘b‘: 2})           # a new counter from a mapping
429         >>> c = Counter(a=4, b=2)                   # a new counter from keyword args
430
431         ‘‘‘
432         if not args:
433             raise TypeError("descriptor ‘__init__‘ of ‘Counter‘ object "
434                             "needs an argument")
435         self = args[0]
436         args = args[1:]
437         if len(args) > 1:
438             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
439         super(Counter, self).__init__()
440         self.update(*args, **kwds)
441
442     def __missing__(self, key):
443         ‘The count of elements not in the Counter is zero.‘
444         # Needed so that self[missing_item] does not raise KeyError
445         return 0
446
447     def most_common(self, n=None):
448         ‘‘‘List the n most common elements and their counts from the most
449         common to the least.  If n is None, then list all element counts.
450
451         >>> Counter(‘abcdeabcdabcaba‘).most_common(3)
452         [(‘a‘, 5), (‘b‘, 4), (‘c‘, 3)]
453
454         ‘‘‘
455         # Emulate Bag.sortedByCount from Smalltalk
456         if n is None:
457             return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
458         return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1))
459
460     def elements(self):
461         ‘‘‘Iterator over elements repeating each as many times as its count.
462
463         >>> c = Counter(‘ABCABC‘)
464         >>> sorted(c.elements())
465         [‘A‘, ‘A‘, ‘B‘, ‘B‘, ‘C‘, ‘C‘]
466
467         # Knuth‘s example for prime factors of 1836:  2**2 * 3**3 * 17**1
468         >>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
469         >>> product = 1
470         >>> for factor in prime_factors.elements():     # loop over factors
471         ...     product *= factor                       # and multiply them
472         >>> product
473         1836
474
475         Note, if an element‘s count has been set to zero or is a negative
476         number, elements() will ignore it.
477
478         ‘‘‘
479         # Emulate Bag.do from Smalltalk and Multiset.begin from C++.
480         return _chain.from_iterable(_starmap(_repeat, self.iteritems()))
481
482     # Override dict methods where necessary
483
484     @classmethod
485     def fromkeys(cls, iterable, v=None):
486         # There is no equivalent method for counters because setting v=1
487         # means that no element can have a count greater than one.
488         raise NotImplementedError(
489             ‘Counter.fromkeys() is undefined.  Use Counter(iterable) instead.‘)
490
491     def update(*args, **kwds):
492         ‘‘‘Like dict.update() but add counts instead of replacing them.
493
494         Source can be an iterable, a dictionary, or another Counter instance.
495
496         >>> c = Counter(‘which‘)
497         >>> c.update(‘witch‘)           # add elements from another iterable
498         >>> d = Counter(‘watch‘)
499         >>> c.update(d)                 # add elements from another counter
500         >>> c[‘h‘]                      # four ‘h‘ in which, witch, and watch
501         4
502
503         ‘‘‘
504         # The regular dict.update() operation makes no sense here because the
505         # replace behavior results in the some of original untouched counts
506         # being mixed-in with all of the other counts for a mismash that
507         # doesn‘t have a straight-forward interpretation in most counting
508         # contexts.  Instead, we implement straight-addition.  Both the inputs
509         # and outputs are allowed to contain zero and negative counts.
510
511         if not args:
512             raise TypeError("descriptor ‘update‘ of ‘Counter‘ object "
513                             "needs an argument")
514         self = args[0]
515         args = args[1:]
516         if len(args) > 1:
517             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
518         iterable = args[0] if args else None
519         if iterable is not None:
520             if isinstance(iterable, Mapping):
521                 if self:
522                     self_get = self.get
523                     for elem, count in iterable.iteritems():
524                         self[elem] = self_get(elem, 0) + count
525                 else:
526                     super(Counter, self).update(iterable) # fast path when counter is empty
527             else:
528                 self_get = self.get
529                 for elem in iterable:
530                     self[elem] = self_get(elem, 0) + 1
531         if kwds:
532             self.update(kwds)
533
534     def subtract(*args, **kwds):
535         ‘‘‘Like dict.update() but subtracts counts instead of replacing them.
536         Counts can be reduced below zero.  Both the inputs and outputs are
537         allowed to contain zero and negative counts.
538
539         Source can be an iterable, a dictionary, or another Counter instance.
540
541         >>> c = Counter(‘which‘)
542         >>> c.subtract(‘witch‘)             # subtract elements from another iterable
543         >>> c.subtract(Counter(‘watch‘))    # subtract elements from another counter
544         >>> c[‘h‘]                          # 2 in which, minus 1 in witch, minus 1 in watch
545         0
546         >>> c[‘w‘]                          # 1 in which, minus 1 in witch, minus 1 in watch
547         -1
548
549         ‘‘‘
550         if not args:
551             raise TypeError("descriptor ‘subtract‘ of ‘Counter‘ object "
552                             "needs an argument")
553         self = args[0]
554         args = args[1:]
555         if len(args) > 1:
556             raise TypeError(‘expected at most 1 arguments, got %d‘ % len(args))
557         iterable = args[0] if args else None
558         if iterable is not None:
559             self_get = self.get
560             if isinstance(iterable, Mapping):
561                 for elem, count in iterable.items():
562                     self[elem] = self_get(elem, 0) - count
563             else:
564                 for elem in iterable:
565                     self[elem] = self_get(elem, 0) - 1
566         if kwds:
567             self.subtract(kwds)
568
569     def copy(self):
570         ‘Return a shallow copy.‘
571         return self.__class__(self)
572
573     def __reduce__(self):
574         return self.__class__, (dict(self),)
575
576     def __delitem__(self, elem):
577         ‘Like dict.__delitem__() but does not raise KeyError for missing values.‘
578         if elem in self:
579             super(Counter, self).__delitem__(elem)
580
581     def __repr__(self):
582         if not self:
583             return ‘%s()‘ % self.__class__.__name__
584         items = ‘, ‘.join(map(‘%r: %r‘.__mod__, self.most_common()))
585         return ‘%s({%s})‘ % (self.__class__.__name__, items)
586
587     # Multiset-style mathematical operations discussed in:
588     #       Knuth TAOCP Volume II section 4.6.3 exercise 19
589     #       and at http://en.wikipedia.org/wiki/Multiset
590     #
591     # Outputs guaranteed to only include positive counts.
592     #
593     # To strip negative and zero counts, add-in an empty counter:
594     #       c += Counter()
595
596     def __add__(self, other):
597         ‘‘‘Add counts from two counters.
598
599         >>> Counter(‘abbb‘) + Counter(‘bcc‘)
600         Counter({‘b‘: 4, ‘c‘: 2, ‘a‘: 1})
601
602         ‘‘‘
603         if not isinstance(other, Counter):
604             return NotImplemented
605         result = Counter()
606         for elem, count in self.items():
607             newcount = count + other[elem]
608             if newcount > 0:
609                 result[elem] = newcount
610         for elem, count in other.items():
611             if elem not in self and count > 0:
612                 result[elem] = count
613         return result
614
615     def __sub__(self, other):
616         ‘‘‘ Subtract count, but keep only results with positive counts.
617
618         >>> Counter(‘abbbc‘) - Counter(‘bccd‘)
619         Counter({‘b‘: 2, ‘a‘: 1})
620
621         ‘‘‘
622         if not isinstance(other, Counter):
623             return NotImplemented
624         result = Counter()
625         for elem, count in self.items():
626             newcount = count - other[elem]
627             if newcount > 0:
628                 result[elem] = newcount
629         for elem, count in other.items():
630             if elem not in self and count < 0:
631                 result[elem] = 0 - count
632         return result
633
634     def __or__(self, other):
635         ‘‘‘Union is the maximum of value in either of the input counters.
636
637         >>> Counter(‘abbb‘) | Counter(‘bcc‘)
638         Counter({‘b‘: 3, ‘c‘: 2, ‘a‘: 1})
639
640         ‘‘‘
641         if not isinstance(other, Counter):
642             return NotImplemented
643         result = Counter()
644         for elem, count in self.items():
645             other_count = other[elem]
646             newcount = other_count if count < other_count else count
647             if newcount > 0:
648                 result[elem] = newcount
649         for elem, count in other.items():
650             if elem not in self and count > 0:
651                 result[elem] = count
652         return result
653
654     def __and__(self, other):
655         ‘‘‘ Intersection is the minimum of corresponding counts.
656
657         >>> Counter(‘abbb‘) & Counter(‘bcc‘)
658         Counter({‘b‘: 1})
659
660         ‘‘‘
661         if not isinstance(other, Counter):
662             return NotImplemented
663         result = Counter()
664         for elem, count in self.items():
665             other_count = other[elem]
666             newcount = count if count < other_count else other_count
667             if newcount > 0:
668                 result[elem] = newcount
669         return result
670
671
672 if __name__ == ‘__main__‘:
673     # verify that instances can be pickled
674     from cPickle import loads, dumps
675     Point = namedtuple(‘Point‘, ‘x, y‘, True)
676     p = Point(x=10, y=20)
677     assert p == loads(dumps(p))
678
679     # test and demonstrate ability to override methods
680     class Point(namedtuple(‘Point‘, ‘x y‘)):
681         __slots__ = ()
682         @property
683         def hypot(self):
684             return (self.x ** 2 + self.y ** 2) ** 0.5
685         def __str__(self):
686             return ‘Point: x=%6.3f  y=%6.3f  hypot=%6.3f‘ % (self.x, self.y, self.hypot)
687
688     for p in Point(3, 4), Point(14, 5/7.):
689         print p
690
691     class Point(namedtuple(‘Point‘, ‘x y‘)):
692         ‘Point class with optimized _make() and _replace() without error-checking‘
693         __slots__ = ()
694         _make = classmethod(tuple.__new__)
695         def _replace(self, _map=map, **kwds):
696             return self._make(_map(kwds.get, (‘x‘, ‘y‘), self))
697
698     print Point(11, 22)._replace(x=100)
699
700     Point3D = namedtuple(‘Point3D‘, Point._fields + (‘z‘,))
701     print Point3D.__doc__
702
703     import doctest
704     TestResults = namedtuple(‘TestResults‘, ‘failed attempted‘)
705     print TestResults(*doctest.testmod())

普通字典是无序的,这里是介绍有序字典,具体方法如下

 1 >>> import collections
 2 >>> c1 = collections.OrderedDict()
 3 >>> c1[‘k1‘] = 1
 4 >>> c1[‘k2‘] = 2
 5 >>> c1[‘k3‘] = 3
 6 >>> c1
 7 OrderedDict([(‘k1‘, 1), (‘k2‘, 2), (‘k3‘, 3)])  有序
 8 >>> c2 = {}
 9 >>> c2[‘k1‘] = 1
10 >>> c2[‘k2‘] = 2
11 >>> c2[‘k3‘] = 3
12 >>> c2
13 {‘k3‘: 3, ‘k2‘: 2, ‘k1‘: 1}   无序

3默认字典

时间: 2024-10-05 03:40:26

python之旅3的相关文章

开始 Python 之旅

开始 Python 之旅 课程来源 本课程基于 Python for you and me 教程翻译制作,其中参考了 Python tutorial 和 The Python Standard Library,并对原教程的内容进行了改进与补充. 相关链接地址如下: Python tutorial:http://www.pythondoc.com/pythontutorial3/index.html Python for you and me:http://pymbook.readthedocs.

day1-开启python之旅

1.python安装Anaconda安装地址:https://www.anaconda.com/2.Pycharm安装 Pycharm安装地址:https://www.jetbrains.com/pycharm/3.安装环境测试 python3.6.2+Pycharm:4.建立项目及新建.py文件并打印输输出 print('hello world') 准备就绪,开始python之旅吧 原文地址:http://blog.51cto.com/13803166/2128333

Python之旅(七)面向对象

三大编程范式 三大编程范式(这三者各有千秋,不分好坏): 面向过程编程 函数式编程 面向对象编程 面向过程编程 “面向过程”(Procedure Oriented)是一种以过程为中心的编程思想. 过程是指解决问题的步骤.例如问题:如何把大象放入一个冰箱?步骤:先打开冰箱,在将大象放入冰箱,最后关上冰箱.面向过程是一种较机械式的思维方式. 优点: 复杂的问题流程化,进而简单化(一个复杂的问题,分成一个个小的步骤去实现,实现小的步骤将会非常简单). 性能比面向对象高,因为类调用时需要实例化,比较消耗

python之旅六【第六篇】模块

json和pickle 用于序列化的两个模块 json,用于字符串 和 python数据类型间进行转换pickle,用于python特有的类型 和 python的数据类型间进行转换 json模块提供了四个功能:dumps.dump.loads.loadpickle模块提供了四个功能:dumps.dump.loads.load json dumps把数据类型转换成字符串 dump把数据类型转换成字符串并存储在文件中  loads把字符串转换成数据类型  load把文件打开从字符串转换成数据类型

python之旅2

python基础 1整数 查看整数类型的方法 >>> a = 1 >>> dir(a) ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getn

【Python之旅】第五篇(四):基于Python Sockct多线程的简版SSH程序

还是继续延续篇五中前三节的例子,通过对代码的修修补补,把它改成一个可以在连接后就能在Client端执行Server端命令的程序,所以就有点类似于SSH连接程序了. 至于还是用前面的例子来改嘛,是因为上课也一直这么干,而且老师也讲得非常不错,自己吸收后也作为一个学习的记录吧,因为确实是非常不错的! 之所以能对前面的例子如这样的修改,应当有这样的思想:前面的例子中,Server端能够返回Client端输入的字符串,那么如果Client端输入的是Linux的shell命令,Server端是否可以执行这

【Python之旅】第五篇(一):Python Socket通信原理

只要和网络服务涉及的,就离不开Socket以及Socket编程,下面就说说Python Socket通信的基本原理. 1.Socket socket也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求.可以列举中国移动或者是中国电信等的电话客服,当然,也可以看下面的图片来作形象的说明. socket起源于Unix,而Unix/Linux基本哲学之一就是:一切皆文件,即都可以用"打开open-

【Python之旅】第五篇(二):Python Socket单线程+阻塞模式

前面第五篇(一)中的一个Socket例子其实就是单线程的,即Server端一次只能接受来自一个Client端的连接,为了更好的说明socket单线程和阻塞模式,下面对前面的例子做修改. 1.单线程+阻塞+交互式 前面的例子是单线程阻塞和非交互式的,现在改写为交互式的,即不会执行一次就结束,希望达到的效果是,发送的数据由User输入,然后Server端进行接收. Server端:与上个例子一样,并没有什么变化 import socket                #导入socket类   HO

【Python之旅】第三篇(一):Python函数

说明: 使用函数可以使程序实现功能模块化,大大简洁我们的程序,这里主要讨论Python中函数的下列内容: 1.函数定义与函数参数 2.局部变量和全局变量 3.函数默认参数和关键参数 4.*Args和**Kargs 因为函数部分内容跟C语言中的很多内容都十分相似,所以会结合C语言来进行对比学习. 1.函数定义与函数参数 --基本格式1:不参参数 ·定义: def sayHi():     print "Hello!" ·调用: >>> sayHi() Hello --基

【Python之旅】第二篇(九):迭代器

说明:关于Python中迭代器的解释 Iterator是迭代器的意思,它的作用是一次产生一个数据项,直到没有为止.这样在 for 循环中就可以对它进行循环处理了.那么它与一般的序列类型(list, tuple等)有什么区别呢?它一次只返回一个数据项,占用更少的内存.但它需要记住当前的状态,以便返回下一数据项.它是一个有着next()方法的对象.而序列类型则保存了所有的数据项,它们的访问是通过索引进行的. 举个前面的例子来说就像readlines和xreadlines的区别,readlines是一