您的位置:首页 > 编程语言 > Python开发

python学习笔记-Day03 -第一部分(collections,Counter,defaultdict,namedtuple)

2015-11-09 17:55 633 查看
先做两个练习题:
第一题:

有如下集合 [11, 22, 33, 44, 55, 66, 77, 88, 99]
将所有大于66的值保存在字典的的第一个key中,小于等于66的值保存在k2中;
即:
{'k2':[77, 88, 99],'k1':[11, 22, 33, 44, 55, 66]}

code:

dic ={}
for i in range(11,100,11):
if i <=66:
if 'k1' in dic:
dic['k1'].append(i)
else:
dic['k1']=[i,]
else:
if 'k2' in dic:
dic['k2'].append(i)
else:
dic['k2']=[i,]
for m in dic:
print m,dic[m]


第二题:
现在有文件 info.db ,内容如下
alex:123:1
eric:123:1
hope:123:1
读取文件内容,并生成如下格式的字典
{'alex': ['123', '1'], 'eric': ['123', '1'], 'hope': ['123', '1']}

code:

with open('info.db','r') as info_f:
userinfo = info_f.readlines()
dic_userinfo={}
for i in userinfo:
tmp_user_info_lst = i.strip().split(':')
# print tmp_user_info_lst
for var in tmp_user_info_lst[1:]:
# print var,'--',
if tmp_user_info_lst[0] in dic_userinfo:
dic_userinfo[tmp_user_info_lst[0]].append(var)
else:
dic_userinfo[tmp_user_info_lst[0]]=[var,]
print dic_userinfo
##   或者  ###################################
with open('info.db','r') as info_f:
userinfo = info_f.readlines()
dic_userinfo={}
for i in userinfo:
tmp_user_info_lst = i.strip().split(':')
# print tmp_user_info_lst
dic_userinfo[tmp_user_info_lst[0]]=tmp_user_info_lst[1:]
print dic_userinfo


##########################################################
collections
计数器(Counter)
Counter是对字典的扩展,Counter继承了字典,是对字典的补充,具有字典的所有功能,用于追踪值 出现的次数

class Counter(dict):
'''Dict subclass for counting hashable items. Sometimes called a bag
or multiset. Elements are stored as dictionary keys and their counts
are stored as dictionary values.

>>> c = Counter('abcdeabcdabcaba') # count elements from a string

>>> c.most_common(3) # three most common elements
[('a', 5), ('b', 4), ('c', 3)]
>>> sorted(c) # list all unique elements
['a', 'b', 'c', 'd', 'e']
>>> ''.join(sorted(c.elements())) # list elements with repetitions
'aaaaabbbbcccdde'
>>> sum(c.values()) # total of all counts
15

>>> c['a'] # count of letter 'a'
5
>>> for elem in 'shazam': # update counts from an iterable
... c[elem] += 1 # by adding 1 to each element's count
>>> c['a'] # now there are seven 'a'
7
>>> del c['b'] # remove all 'b'
>>> c['b'] # now there are zero 'b'
0

>>> d = Counter('simsalabim') # make another counter
>>> c.update(d) # add in the second counter
>>> c['a'] # now there are nine 'a'
9

>>> c.clear() # empty the counter
>>> c
Counter()

Note: If a count is set to zero or reduced to zero, it will remain
in the counter until the entry is deleted or the counter is cleared:

>>> c = Counter('aaabbc')
>>> c['b'] -= 2 # reduce the count of 'b' by two
>>> c.most_common() # 'b' is still in, but its count is zero
[('a', 3), ('c', 1), ('b', 0)]

'''
# References:
# http://en.wikipedia.org/wiki/Multiset # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm # http://code.activestate.com/recipes/259174/ # Knuth, TAOCP Vol. II section 4.6.3

def __init__(self, iterable=None, **kwds):
'''Create a new, empty Counter object. And if given, count elements
from an input iterable. Or, initialize the count from another mapping
of elements to their counts.

>>> c = Counter() # a new, empty counter
>>> c = Counter('gallahad') # a new counter from an iterable
>>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping
>>> c = Counter(a=4, b=2) # a new counter from keyword args

'''
super(Counter, self).__init__()
self.update(iterable, **kwds)

def __missing__(self, key):
'The count of elements not in the Counter is zero.'

""" 对于不存在的元素,返回计数器0"""
# Needed so that self[missing_item] does not raise KeyError
return 0

def most_common(self, n=None):
'''List the n most common elements and their counts from the most
common to the least. If n is None, then list all element counts.

>>> Counter('abcdeabcdabcaba').most_common(3)
[('a', 5), ('b', 4), ('c', 3)]

列出出现次数最多的元素,参数为几 则输出前几个

'''
# Emulate Bag.sortedByCount from Smalltalk
if n is None:
return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1))

def elements(self):
'''Iterator over elements repeating each as many times as its count.
返回一个 迭代器(只有循环的时候才可以从迭代器中获取元素)
迭代器中包括所有的元素,此处非所有元素,而是所有元素集合的迭代器

>>> c = Counter('ABCABC')
>>> sorted(c.elements())
['A', 'A', 'B', 'B', 'C', 'C']

# Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
>>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
>>> product = 1
>>> for factor in prime_factors.elements(): # loop over factors
... product *= factor # and multiply them
>>> product
1836

Note, if an element's count has been set to zero or is a negative
number, elements() will ignore it.

'''
# Emulate Bag.do from Smalltalk and Multiset.begin from C++.
return _chain.from_iterable(_starmap(_repeat, self.iteritems()))

# Override dict methods where necessary

@classmethod
def fromkeys(cls, iterable, v=None):
# There is no equivalent method for counters because setting v=1
# means that no element can have a count greater than one.
raise NotImplementedError(
'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')

def update(self, iterable=None, **kwds):
'''Like dict.update() but add counts instead of replacing them.

更新计数器,其实就是增加,如果原来没有,则新建,如果有有则加一
Source can be an iterable, a dictionary, or another Counter instance.

>>> c = Counter('which')
>>> c.update('witch') # add elements from another iterable
>>> d = Counter('watch')
>>> c.update(d) # add elements from another counter
>>> c['h'] # four 'h' in which, witch, and watch
4

'''
# The regular dict.update() operation makes no sense here because the
# replace behavior results in the some of original untouched counts
# being mixed-in with all of the other counts for a mismash that
# doesn't have a straight-forward interpretation in most counting
# contexts. Instead, we implement straight-addition. Both the inputs
# and outputs are allowed to contain zero and negative counts.

if iterable is not None:
if isinstance(iterable, Mapping):
if self:
self_get = self.get
for elem, count in iterable.iteritems():
self[elem] = self_get(elem, 0) + count
else:
super(Counter, self).update(iterable) # fast path when counter is empty
else:
self_get = self.get
for elem in iterable:
self[elem] = self_get(elem, 0) + 1
if kwds:
self.update(kwds)

def subtract(self, iterable=None, **kwds):
'''
相减,原来的计数器中的每一个元素的数量减去后添加的元素的数量

Like dict.update() but subtracts counts instead of replacing them.
Counts can be reduced below zero. Both the inputs and outputs are
allowed to contain zero and negative counts.

Source can be an iterable, a dictionary, or another Counter instance.

>>> c = Counter('which')
>>> c.subtract('witch') # subtract elements from another iterable
>>> c.subtract(Counter('watch')) # subtract elements from another counter
>>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch
0
>>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch
-1

'''
if iterable is not None:
self_get = self.get
if isinstance(iterable, Mapping):
for elem, count in iterable.items():
self[elem] = self_get(elem, 0) - count
else:
for elem in iterable:
self[elem] = self_get(elem, 0) - 1
if kwds:
self.subtract(kwds)

def copy(self):
'Return a shallow copy. 拷贝'
return self.__class__(self)

def __reduce__(self):
“”“ 返回一个元素 (类型,元组)”“”

return self.__class__, (dict(self),)

def __delitem__(self, elem):
'Like dict.__delitem__() but does not raise KeyError for missing values.'
'删除元素'

if elem in self:
super(Counter, self).__delitem__(elem)

def __repr__(self):
if not self:
return '%s()' % self.__class__.__name__
items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
return '%s({%s})' % (self.__class__.__name__, items)

# Multiset-style mathematical operations discussed in:
# Knuth TAOCP Volume II section 4.6.3 exercise 19
# and at http://en.wikipedia.org/wiki/Multiset #
# Outputs guaranteed to only include positive counts.
#
# To strip negative and zero counts, add-in an empty counter:
# c += Counter()

def __add__(self, other):
'''Add counts from two counters.

>>> Counter('abbb') + Counter('bcc')
Counter({'b': 4, 'c': 2, 'a': 1})

'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem, count in self.items():
newcount = count + other[elem]
if newcount > 0:
result[elem] = newcount
for elem, count in other.items():
if elem not in self and count > 0:
result[elem] = count
return result

def __sub__(self, other):
''' Subtract count, but keep only results with positive counts.

>>> Counter('abbbc') - Counter('bccd')
Counter({'b': 2, 'a': 1})

'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem, count in self.items():
newcount = count - other[elem]
if newcount > 0:
result[elem] = newcount
for elem, count in other.items():
if elem not in self and count < 0:
result[elem] = 0 - count
return result

def __or__(self, other):
'''Union is the maximum of value in either of the input counters.

>>> Counter('abbb') | Counter('bcc')
Counter({'b': 3, 'c': 2, 'a': 1})

'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem, count in self.items():
other_count = other[elem]
newcount = other_count if count < other_count else count
if newcount > 0:
result[elem] = newcount
for elem, count in other.items():
if elem not in self and count > 0:
result[elem] = count
return result

def __and__(self, other):
''' Intersection is the minimum of corresponding counts.

>>> Counter('abbb') & Counter('bcc')
Counter({'b': 1})

'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem, count in self.items():
other_count = other[elem]
newcount = count if count < other_count else other_count
if newcount > 0:
result[elem] = newcount
return result

if __name__ == '__main__':
# verify that instances can be pickled
from cPickle import loads, dumps
Point = namedtuple('Point', 'x, y', True)
p = Point(x=10, y=20)
assert p == loads(dumps(p))

# test and demonstrate ability to override methods
class Point(namedtuple('Point', 'x y')):
__slots__ = ()
@property
def hypot(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
def __str__(self):
return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)

for p in Point(3, 4), Point(14, 5/7.):
print p

class Point(namedtuple('Point', 'x y')):
'Point class with optimized _make() and _replace() without error-checking'
__slots__ = ()
_make = classmethod(tuple.__new__)
def _replace(self, _map=map, **kwds):
return self._make(_map(kwds.get, ('x', 'y'), self))

print Point(11, 22)._replace(x=100)

Point3D = namedtuple('Point3D', Point._fields + ('z',))
print Point3D.__doc__

import doctest
TestResults = namedtuple('TestResults', 'failed attempted')
print TestResults(*doctest.testmod())

######################################################################################
有序字典
collections.OrderedDict
有顺序的字典
class OrderedDict(dict):
'Dictionary that remembers insertion order'
# An inherited dict maps keys to values.
# The inherited dict provides __getitem__, __len__, __contains__, and get.
# The remaining methods are order-aware.
# Big-O running times for all methods are the same as regular dictionaries.

# The internal self.__map dict maps keys to links in a doubly linked list.
# The circular doubly linked list starts and ends with a sentinel element.
# The sentinel element never gets deleted (this simplifies the algorithm).
# Each link is stored as a list of length three: [PREV, NEXT, KEY].

def __init__(self, *args, **kwds):
'''Initialize an ordered dictionary. The signature is the same as
regular dictionaries, but keyword arguments are not recommended because
their insertion order is arbitrary.

'''
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
try:
self.__root
except AttributeError:
self.__root = root = [] # sentinel node
root[:] = [root, root, None]
self.__map = {}
self.__update(*args, **kwds)

def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
'od.__setitem__(i, y) <==> od[i]=y'
# Setting a new item creates a new link at the end of the linked list,
# and the inherited dictionary is updated with the new key/value pair.
if key not in self:
root = self.__root
last = root[0]
last[1] = root[0] = self.__map[key] = [last, root, key]
return dict_setitem(self, key, value)

def __delitem__(self, key, dict_delitem=dict.__delitem__):
'od.__delitem__(y) <==> del od[y]'
# Deleting an existing item uses self.__map to find the link which gets
# removed by updating the links in the predecessor and successor nodes.
dict_delitem(self, key)
link_prev, link_next, _ = self.__map.pop(key)
link_prev[1] = link_next # update link_prev[NEXT]
link_next[0] = link_prev # update link_next[PREV]

def __iter__(self):
'od.__iter__() <==> iter(od)'
# Traverse the linked list in order.
root = self.__root
curr = root[1] # start at the first node
while curr is not root:
yield curr[2] # yield the curr[KEY]
curr = curr[1] # move to next node

def __reversed__(self):
'od.__reversed__() <==> reversed(od)'
# Traverse the linked list in reverse order.
root = self.__root
curr = root[0] # start at the last node
while curr is not root:
yield curr[2] # yield the curr[KEY]
curr = curr[0] # move to previous node

def clear(self):
'od.clear() -> None. Remove all items from od.'
root = self.__root
root[:] = [root, root, None]
self.__map.clear()
dict.clear(self)

# -- the following methods do not depend on the internal structure --

def keys(self):
'od.keys() -> list of keys in od'
return list(self)

def values(self):
'od.values() -> list of values in od'
return [self[key] for key in self]

def items(self):
'od.items() -> list of (key, value) pairs in od'
return [(key, self[key]) for key in self]

def iterkeys(self):
'od.iterkeys() -> an iterator over the keys in od'
return iter(self)

def itervalues(self):
'od.itervalues -> an iterator over the values in od'
for k in self:
yield self[k]

def iteritems(self):
'od.iteritems -> an iterator over the (key, value) pairs in od'
for k in self:
yield (k, self[k])

update = MutableMapping.update

__update = update # let subclasses override update without breaking __init__

__marker = object()

def pop(self, key, default=__marker):
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding
value. If key is not found, d is returned if given, otherwise KeyError
is raised.

'''
if key in self:
result = self[key]
del self[key]
return result
if default is self.__marker:
raise KeyError(key)
return default

def setdefault(self, key, default=None):
'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
if key in self:
return self[key]
self[key] = default
return default

def popitem(self, last=True):
'''od.popitem() -> (k, v), return and remove a (key, value) pair.
Pairs are returned in LIFO order if last is true or FIFO order if false.

'''
if not self:
raise KeyError('dictionary is empty')
key = next(reversed(self) if last else iter(self))
value = self.pop(key)
return key, value

def __repr__(self, _repr_running={}):
'od.__repr__() <==> repr(od)'
call_key = id(self), _get_ident()
if call_key in _repr_running:
return '...'
_repr_running[call_key] = 1
try:
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items())
finally:
del _repr_running[call_key]

def __reduce__(self):
'Return state information for pickling'
items = [[k, self[k]] for k in self]
inst_dict = vars(self).copy()
for k in vars(OrderedDict()):
inst_dict.pop(k, None)
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)

def copy(self):
'od.copy() -> a shallow copy of od'
return self.__class__(self)

@classmethod
def fromkeys(cls, iterable, value=None):
'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
If not specified, the value defaults to None.

'''
self = cls()
for key in iterable:
self[key] = value
return self

def __eq__(self, other):
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
while comparison to a regular mapping is order-insensitive.

'''
if isinstance(other, OrderedDict):
return dict.__eq__(self, other) and all(_imap(_eq, self, other))
return dict.__eq__(self, other)

def __ne__(self, other):
'od.__ne__(y) <==> od!=y'
return not self == other

# -- the following methods support python 3.x style dictionary views --

def viewkeys(self):
"od.viewkeys() -> a set-like object providing a view on od's keys"
return KeysView(self)

def viewvalues(self):
"od.viewvalues() -> an object providing a view on od's values"
return ValuesView(self)

def viewitems(self):
"od.viewitems() -> a set-like object providing a view on od's items"
return ItemsView(self)

######################################################################################
默认字典
collections.defaultdict
为字典的value 设置一个默认类型,

例:
dic = collections.defaultdict(list)
#dic的默认的key对应的值为空列表

class defaultdict(dict):
"""
defaultdict(default_factory[, ...]) --> dict with default factory

The default factory is called without arguments to produce
a new value when a key is not present, in __getitem__ only.
A defaultdict compares equal to a dict with the same items.
All remaining arguments are treated the same as if they were
passed to the dict constructor, including keyword arguments.
"""
def copy(self): # real signature unknown; restored from __doc__
""" D.copy() -> a shallow copy of D. """
pass

def __copy__(self, *args, **kwargs): # real signature unknown
""" D.copy() -> a shallow copy of D. """
pass

def __getattribute__(self, name): # real signature unknown; restored from __doc__
""" x.__getattribute__('name') <==> x.name """
pass

def __init__(self, default_factory=None, **kwargs): # known case of _collections.defaultdict.__init__
"""
defaultdict(default_factory[, ...]) --> dict with default factory

The default factory is called without arguments to produce
a new value when a key is not present, in __getitem__ only.
A defaultdict compares equal to a dict with the same items.
All remaining arguments are treated the same as if they were
passed to the dict constructor, including keyword arguments.

# (copied from class doc)
"""
pass

def __missing__(self, key): # real signature unknown; restored from __doc__
"""
__missing__(key) # Called by __getitem__ for missing key; pseudo-code:
if self.default_factory is None: raise KeyError((key,))
self[key] = value = self.default_factory()
return value
"""
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __repr__(self): # real signature unknown; restored from __doc__
""" x.__repr__() <==> repr(x) """
pass

default_factory = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
"""Factory for default value called by __missing__()."""

######################################################################################
可命名元组(namedtuple)

>>> import collections
>>> mytuple = collections.namedtuple('mytu',['x','y'])
>>> n = mytuple(1,2)
>>> n
mytu(x=1, y=2)
>>> n.x
1
>>> n.y
2

help(mytuple)

Help on class mytu in module __main__:

class mytu(__builtin__.tuple)
| mytu(x, y)
|
| Method resolution order:
| mytu
| __builtin__.tuple
| __builtin__.object
|
| Methods defined here:
|
| __getnewargs__(self)
| Return self as a plain tuple. Used by copy and pickle.
|
| __getstate__(self)
| Exclude the OrderedDict from pickling
|
| __repr__(self)
| Return a nicely formatted representation string
|
| _asdict(self)
| Return a new OrderedDict which maps field names to their values
|
| _replace(_self, **kwds)
| Return a new mytu object replacing specified fields with new values
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| _make(cls, iterable, new=<built-in method __new__ of type object>, len=<built-in function len>) from __builtin__.type
| Make a new mytu object from a sequence or iterable
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(_cls, x, y)
| Create new instance of mytu(x, y)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| Return a new OrderedDict which maps field names to their values
|
| x
| Alias for field number 0
|
| y
| Alias for field number 1
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| _fields = ('x', 'y')
|
| ----------------------------------------------------------------------
| Methods inherited from __builtin__.tuple:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __eq__(...)
| x.__eq__(y) <==> x==y
|
| __ge__(...)
| x.__ge__(y) <==> x>=y
|
| __getattribute__(...)
| x.__getattribute__('name') <==> x.name
|
| __getitem__(...)
| x.__getitem__(y) <==> x[y]
|
| __getslice__(...)
| x.__getslice__(i, j) <==> x[i:j]
|
| Use of negative indices is not supported.
|
| __gt__(...)
| x.__gt__(y) <==> x>y
|
| __hash__(...)
| x.__hash__() <==> hash(x)
|
| __iter__(...)
| x.__iter__() <==> iter(x)
|
| __le__(...)
| x.__le__(y) <==> x<=y
|
| __len__(...)
| x.__len__() <==> len(x)
|
| __lt__(...)
| x.__lt__(y) <==> x<y
|
| __mul__(...)
| x.__mul__(n) <==> x*n
|
| __ne__(...)
| x.__ne__(y) <==> x!=y
|
| __rmul__(...)
| x.__rmul__(n) <==> n*x
|
| __sizeof__(...)
| T.__sizeof__() -- size of T in memory, in bytes
|
| count(...)
| T.count(value) -> integer -- return number of occurrences of value
|
| index(...)
| T.index(value, [start, [stop]]) -> integer -- return first index of value.
| Raises ValueError if the value is not present.

51cto博客地址 http://timesnotes.blog.51cto.com http://timesnotes.blog.51cto.com/1079212/1711125
本博客地址: http://www.timesnotes.com/ http://www.timesnotes.com/?p=84

本文出自 “Will的笔记” 博客,请务必保留此出处http://timesnotes.blog.51cto.com/1079212/1711125
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: