内容参考:Teacher Wu's Blog
一、练习题
写在前:香蕉个芭辣,手一抖,把两周的blog清个干净,重写基础C篇。先来几个练习题压压惊!
1、把列表 lis 中的数值分类,将大于66的放在字典k1中,其它放在k2中
lis = [11,22,33,44,55,66,77,88,99]
dic = {'k1':[],'k2':[]}
for i in lis:
if i > 66:
dic['k1'].append(i)
else:
dic['k2'].append(i)
print dic
## {'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]}
2、上面的也太简单了,那么来个加点难度的,字典是个空的呢
lis = [11,22,33,44,55,66,77,88,99]
dic = {}
for i in lis:
if i > 66:
if 'k1' in dic: # 添加别一个判断,如果'k1'在字典中,那么就添加数据,如果不存在就创建这个key,并添加进去
dic['k1'].append(i) # [i,] 这种添加方式是个亮点,' ,'在这表示后面还有数据喽
else:
dic['k1'] = [i,]
else:
if 'k2' in dic:
dic['k2'].append(i)
else:
dic['k2'] = [i,]
print dic
## {'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]}
3、还敢不敢再来个难点的,将文件中的内容,以字典中套用列表的方式表示出来
dic = {}
with open('db') as read_file: # with 打开文件不用管关闭文件的部分,这个文件句柄执行完后会自动关闭文件
for line in read_file:
line = line.strip()
new_line = line.split('|') # 以'|'将读出来的字符串分割
dic[new_line[0]] = new_line[1:] # 这种用法在以后会经常使用
print dic
## {'kiven': ['333', '0'], 'kim': ['111', '0'], 'tom': ['222', '0']}
二、collection系列
1、计数器(Counter)
Counter是字典类型的补充,用于统计值计算出现的次数,它具备字典的所有功能,同时还有自己扩展的功能
import collections
C = collections.Counter('aaddbbddddeeedfff')
print C
## Counter({'d': 7, 'e': 3, 'f': 3, 'a': 2, 'b': 2})
######################################################################## ### 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 >>> c['a'] # count of letter 'a' >>> 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' >>> del c['b'] # remove all 'b' >>> c['b'] # now there are zero 'b' >>> d = Counter('simsalabim') # make another counter >>> c.update(d) # add in the second counter >>> c['a'] # now there are nine 'a' >>> 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): """ 对于不存在的元素,返回计数器为0 """ 'The count of elements not in the Counter is zero.' # Needed so that self[missing_item] does not raise KeyError return 0 def most_common(self, n=None): """ 数量大于等n的所有元素和计数器 """ '''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 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 ''' # 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 >>> 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
2、有序字典(OrderDict)
OrderDict是字典类型的补充,用于固定元素添加的顺序,内部维护一个列表
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)
3、默认字典(defaultdict)
默认字典是对字典类型的补充,原生字典value的值默认是None,而默认字典可以指定value的类型
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__()."""
上面的写过的练习题2还可以通过默认字典来写哦
from collections import defaultdict lis = [11,22,33,44,55,66,77.88,99] dic = defaultdict(list) # 指定value类型为list for i in lis: if i > 66: if 'k1' in dic: dic['k1'].append(i) else: if 'k2' in dic: dic['k2'].append(i) print dic ## {'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]} 默认字典方式
from collections import defaultdict lis = [11,22,33,44,55,66,77.88,99] dic = defaultdict(list) # 指定value类型为list for i in lis: if i > 66: if 'k1' in dic: dic['k1'].append(i) else: if 'k2' in dic: dic['k2'].append(i) print dic ## {'k2': [11, 22, 33, 44, 55, 66], 'k1': [77, 88, 99]}
4、可命名元组(namedtuple)
可命名元组定义了一个扩展的元组类型
import collections
Mytuple = collections.namedtuple('Mytuple',['x','y'])
new = Mytuple(1,2)
print new,new.x,new.y
## Mytuple(x=1, y=2) 1 2
5、双向队列(deque)
一个线程安全的双向队列,双向插入读取数据
>>> q = collections.deque()
>>> q.append(11)
>>> q.append(22)
>>> q.append(33)
>>> q
deque([11, 22, 33])
>>> q.pop() # pop在这里是拿走后删除的
33
>>> q
deque([11, 22])
>>> q.popleft()
11
>>> q
deque([22])
class deque(object): """ deque([iterable[, maxlen]]) --> deque object Build an ordered collection with optimized access from its endpoints. """ def append(self, *args, **kwargs): # real signature unknown """ Add an element to the right side of the deque. """ pass def appendleft(self, *args, **kwargs): # real signature unknown """ Add an element to the left side of the deque. """ pass def clear(self, *args, **kwargs): # real signature unknown """ Remove all elements from the deque. """ pass def count(self, value): # real signature unknown; restored from __doc__ """ D.count(value) -> integer -- return number of occurrences of value """ return 0 def extend(self, *args, **kwargs): # real signature unknown """ Extend the right side of the deque with elements from the iterable """ pass def extendleft(self, *args, **kwargs): # real signature unknown """ Extend the left side of the deque with elements from the iterable """ pass def pop(self, *args, **kwargs): # real signature unknown """ Remove and return the rightmost element. """ pass def popleft(self, *args, **kwargs): # real signature unknown """ Remove and return the leftmost element. """ pass def remove(self, value): # real signature unknown; restored from __doc__ """ D.remove(value) -- remove first occurrence of value. """ pass def reverse(self): # real signature unknown; restored from __doc__ """ D.reverse() -- reverse *IN PLACE* """ pass def rotate(self, *args, **kwargs): # real signature unknown """ Rotate the deque n steps to the right (default n=1). If n is negative, rotates left. """ pass def __copy__(self, *args, **kwargs): # real signature unknown """ Return a shallow copy of a deque. """ pass def __delitem__(self, y): # real signature unknown; restored from __doc__ """ x.__delitem__(y) <==> del x[y] """ pass def __eq__(self, y): # real signature unknown; restored from __doc__ """ x.__eq__(y) <==> x==y """ pass def __getattribute__(self, name): # real signature unknown; restored from __doc__ """ x.__getattribute__('name') <==> x.name """ pass def __getitem__(self, y): # real signature unknown; restored from __doc__ """ x.__getitem__(y) <==> x[y] """ pass def __ge__(self, y): # real signature unknown; restored from __doc__ """ x.__ge__(y) <==> x>=y """ pass def __gt__(self, y): # real signature unknown; restored from __doc__ """ x.__gt__(y) <==> x>y """ pass def __iadd__(self, y): # real signature unknown; restored from __doc__ """ x.__iadd__(y) <==> x+=y """ pass def __init__(self, iterable=(), maxlen=None): # known case of _collections.deque.__init__ """ deque([iterable[, maxlen]]) --> deque object Build an ordered collection with optimized access from its endpoints. # (copied from class doc) """ pass def __iter__(self): # real signature unknown; restored from __doc__ """ x.__iter__() <==> iter(x) """ pass def __len__(self): # real signature unknown; restored from __doc__ """ x.__len__() <==> len(x) """ pass def __le__(self, y): # real signature unknown; restored from __doc__ """ x.__le__(y) <==> x<=y """ pass def __lt__(self, y): # real signature unknown; restored from __doc__ """ x.__lt__(y) <==> x<y """ pass @staticmethod # known case of __new__ def __new__(S, *more): # real signature unknown; restored from __doc__ """ T.__new__(S, ...) -> a new object with type S, a subtype of T """ pass def __ne__(self, y): # real signature unknown; restored from __doc__ """ x.__ne__(y) <==> x!=y """ 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 def __reversed__(self): # real signature unknown; restored from __doc__ """ D.__reversed__() -- return a reverse iterator over the deque """ pass def __setitem__(self, i, y): # real signature unknown; restored from __doc__ """ x.__setitem__(i, y) <==> x[i]=y """ pass def __sizeof__(self): # real signature unknown; restored from __doc__ """ D.__sizeof__() -- size of D in memory, in bytes """ pass maxlen = property(lambda self: object(), lambda self, v: None, lambda self: None) # default """maximum size of a deque or None if unbounded""" __hash__ = None
6、单向队列(Queue.Queue)
数据写入与读取先进先出原则(FIFO)
>>> import Queue
>>> q = Queue.Queue(10)
>>> q.put(1)
>>> q.put(2)
>>> q.put(3)
>>> q.get()
1
>>> q.get()
2
>>> q.get()
3
class Queue: """Create a queue object with a given maximum size. If maxsize is <= 0, the queue size is infinite. """ def __init__(self, maxsize=0): self.maxsize = maxsize self._init(maxsize) # mutex must be held whenever the queue is mutating. All methods # that acquire mutex must release it before returning. mutex # is shared between the three conditions, so acquiring and # releasing the conditions also acquires and releases mutex. self.mutex = _threading.Lock() # Notify not_empty whenever an item is added to the queue; a # thread waiting to get is notified then. self.not_empty = _threading.Condition(self.mutex) # Notify not_full whenever an item is removed from the queue; # a thread waiting to put is notified then. self.not_full = _threading.Condition(self.mutex) # Notify all_tasks_done whenever the number of unfinished tasks # drops to zero; thread waiting to join() is notified to resume self.all_tasks_done = _threading.Condition(self.mutex) self.unfinished_tasks = 0 def task_done(self): """Indicate that a formerly enqueued task is complete. Used by Queue consumer threads. For each get() used to fetch a task, a subsequent call to task_done() tells the queue that the processing on the task is complete. If a join() is currently blocking, it will resume when all items have been processed (meaning that a task_done() call was received for every item that had been put() into the queue). Raises a ValueError if called more times than there were items placed in the queue. """ self.all_tasks_done.acquire() try: unfinished = self.unfinished_tasks - 1 if unfinished <= 0: if unfinished < 0: raise ValueError('task_done() called too many times') self.all_tasks_done.notify_all() self.unfinished_tasks = unfinished finally: self.all_tasks_done.release() def join(self): """Blocks until all items in the Queue have been gotten and processed. The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls task_done() to indicate the item was retrieved and all work on it is complete. When the count of unfinished tasks drops to zero, join() unblocks. """ self.all_tasks_done.acquire() try: while self.unfinished_tasks: self.all_tasks_done.wait() finally: self.all_tasks_done.release() def qsize(self): """Return the approximate size of the queue (not reliable!).""" self.mutex.acquire() n = self._qsize() self.mutex.release() return n def empty(self): """Return True if the queue is empty, False otherwise (not reliable!).""" self.mutex.acquire() n = not self._qsize() self.mutex.release() return n def full(self): """Return True if the queue is full, False otherwise (not reliable!).""" self.mutex.acquire() n = 0 < self.maxsize == self._qsize() self.mutex.release() return n def put(self, item, block=True, timeout=None): """Put an item into the queue. If optional args 'block' is true and 'timeout' is None (the default), block if necessary until a free slot is available. If 'timeout' is a non-negative number, it blocks at most 'timeout' seconds and raises the Full exception if no free slot was available within that time. Otherwise ('block' is false), put an item on the queue if a free slot is immediately available, else raise the Full exception ('timeout' is ignored in that case). """ self.not_full.acquire() try: if self.maxsize > 0: if not block: if self._qsize() == self.maxsize: raise Full elif timeout is None: while self._qsize() == self.maxsize: self.not_full.wait() elif timeout < 0: raise ValueError("'timeout' must be a non-negative number") else: endtime = _time() + timeout while self._qsize() == self.maxsize: remaining = endtime - _time() if remaining <= 0.0: raise Full self.not_full.wait(remaining) self._put(item) self.unfinished_tasks += 1 self.not_empty.notify() finally: self.not_full.release() def put_nowait(self, item): """Put an item into the queue without blocking. Only enqueue the item if a free slot is immediately available. Otherwise raise the Full exception. """ return self.put(item, False) def get(self, block=True, timeout=None): """Remove and return an item from the queue. If optional args 'block' is true and 'timeout' is None (the default), block if necessary until an item is available. If 'timeout' is a non-negative number, it blocks at most 'timeout' seconds and raises the Empty exception if no item was available within that time. Otherwise ('block' is false), return an item if one is immediately available, else raise the Empty exception ('timeout' is ignored in that case). """ self.not_empty.acquire() try: if not block: if not self._qsize(): raise Empty elif timeout is None: while not self._qsize(): self.not_empty.wait() elif timeout < 0: raise ValueError("'timeout' must be a non-negative number") else: endtime = _time() + timeout while not self._qsize(): remaining = endtime - _time() if remaining <= 0.0: raise Empty self.not_empty.wait(remaining) item = self._get() self.not_full.notify() return item finally: self.not_empty.release() def get_nowait(self): """Remove and return an item from the queue without blocking. Only get an item if one is immediately available. Otherwise raise the Empty exception. """ return self.get(False) # Override these methods to implement other queue organizations # (e.g. stack or priority queue). # These will only be called with appropriate locks held # Initialize the queue representation def _init(self, maxsize): self.queue = deque() def _qsize(self, len=len): return len(self.queue) # Put a new item in the queue def _put(self, item): self.queue.append(item) # Get an item from the queue def _get(self): return self.queue.popleft()
7、栈
后进先出(弹夹)
三、迭代器、生成器、冒泡算法、装饰器、递归
1、迭代器
对于Python 列表的 for 循环,他的内部原理:查看下一个元素是否存在,如果存在,则取出,如果不存在,则报异常 StopIteration。(python内部对异常已处理)
2、生成器
range不是生成器,xrange是生成器
readlines是生成器,xreadlines是生成器
print range(10)
print xrange(10)
## [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
## xrange(10)
生成器基于yield创建,对于生成器只有使用时创建,从而避免内在浪费
1 练习:<br>有如下列表: 2 [13, 22, 6, 99, 11] 3 4 # 请按照一下规则计算: 5 # 13 和 22 比较,将大的值放在右侧,即:[13, 22, 6, 99, 11] 6 # 22 和 6 比较,将大的值放在右侧,即:[13, 6, 22, 99, 11] 7 # 22 和 99 比较,将大的值放在右侧,即:[13, 6, 22, 99, 11] 8 # 99 和 42 比较,将大的值放在右侧,即:[13, 6, 22, 11, 99,] 9 # 13 和 6 比较,将大的值放在右侧,即:[6, 13, 22, 11, 99,] 10 ... 11 12 li = [13, 22, 6, 99, 11] 13 14 for m in range(len(li)-1): 15 16 for n in range(m+1, len(li)): 17 if li[m]> li[n]: 18 temp = li[n] 19 li[n] = li[m] 20 li[m] = temp 21 22 print li
3、yield生成器
如果一个def的主体包含yield,这个函数会自动变成一个生成器(即使它包含一个return)。
(1)生成器只有在循环调用的时候才会有结果
def func():
yield 1
yield 2
yield 3
for i in func():
print i
## 1
## 2
## 3
(2)yield用于记住上一次的操作
def func(arg):
seed = 0
while True:
seed += 1
if seed > arg:
return
else:
yield seed
for i in func(3):
print i
## 1
## 2
## 3
4、冒泡算法
需求:请按照从小到大对列表 [13, 22, 6, 99, 11] 进行排序
思路:相邻两个值进行比较,将较大的值放在右侧,依次比较!
(1)在实现之前先做一个小题开胃
# 如何让'11','12'调换位置呢
lis = [11,22]
temp = lis[0]
lis[0] = lis[1]
lis[1] = temp
print lis
## [22, 11]
(2)按两两比较最大的放在右边
# 从左向右两两比较,将最大的放在右边
lis = [13,22,6,99,11]
for m in range(4): # 等价于 for m in range(len(lis)-1):
if lis[m] > lis[m+1]:
temp = lis[m]
lis[m] = lis[m+1]
lis[m+1] = temp
for m in range(3): # 等价于 for m in range(len(lis)-2):
if lis[m] > lis[m+1]:
temp = lis[m]
lis[m] = lis[m+1]
lis[m+1] = temp
for m in range(2): # 等价于 for m in range(len(lis)-3):
if lis[m] > lis[m+1]:
temp = lis[m]
lis[m] = lis[m+1]
lis[m+1] = temp
for m in range(1): # 等价于 for m in range(len(lis)-4):
if lis[m] > lis[m+1]:
temp = lis[m]
lis[m] = lis[m+1]
lis[m+1] = temp
(3)那么冒泡的过程最终可以写成这样
lis = [13,22,6,99,11]
for i in range(1,5):
for m in range(len(lis)-i):
5、被挖了祖坟的装饰器(Decorator)
装饰器是具备特殊意义的函数,装饰器用来装饰函数或类,装饰器可以在函数执行前后添加相应的操作
(1)装饰器的基本形式
def Decorator(func): # 3、将函数体 operation当作参数调用进来 func = operation
def inner():
func() # 5、func() = opeation() = 'operation!'
return inner # 4、返回了一个函数体 Decorator() = inner
@Decorator # 2、装饰器做如下转换:operation = Decorator(operation) = inner()
def operation():
print 'operation!'
operation() # 1、调用函数operation()
## operation!
(2)带参数的装饰器
def Decorator(func): # 4、将代参数的函数体operation传进来 func = operation
def inner(arg): # 7、当第二遍调用时将调用inner(arg)
func(arg) # 8、执行func(arg) = operation(arg) = 'operation ! -- 1'
return inner # 5、返回 代参数的inner operation = inner
@Decorator # 3、装饰器做的操作 operation = Decorator(operration) = inner(代参数的函数体)
def operation(arg): # 2将值1传进来 arg = 1
print "%s -- %s" % ('operation !',arg)
operation(1) # 1、传进值1 # 6、调用inner(arg)
## operation ! -- 1
(3)加入动态参数的装饰器
def Decorator(func):
def inner(*args,**kwargs): # 加入动态参数,那么可以同时满足调用函数加参数与不加参数的情况
func(*args,**kwargs)
return inner
@ Decorator
def operation(arg):
print "%s -- %s" % ('operation !',arg)
@ Decorator
def operation1():
print 'operation1 !'
lis = [11,22,33]
operation(lis)
operation1()
## operation ! -- [11, 22, 33]
## operation1 !
(4)具备返回值的装饰器
def Decorator(func):
def inner(*args,**kwargs):
ret = func(*args,**kwargs)
return ret # 2、那么装饰器内部也要返回调用函数体本身
return inner
@ Decorator
def operation(arg):
lis = [11,22,33]
return lis # 1、函数中返回了内容
print operation('test')
## [11, 22, 33]
(5)装饰器中加入一个用户控制实例
def user_login():
name = 'tom'
if name == 'kim':
return True
else:
return False
def Decorator(func):
def inner(*args,**kwargs):
auth = user_login()
if not auth:
print 'Authentication invalid !'
ret = func(*args,**kwargs)
return ret
return inner
@Decorator
def operation(arg):
lis = [11,22,33]
return lis
print operation('test')
## Authentication invalid !
## [11, 22, 33] # 这所以这行也会打印,是因如果用户条件不成立,那么inner就不会执行,那么装饰器就没有意义了
(6)装饰器中加入一个密码认证实例
def pwd_auth(pwd):
save_pwd= 'aabbcc'
if pwd == save_pwd:
return True
else:
return False
def Decorator(func):
def inner(*args,**kwargs):
keep_key = kwargs.pop('token') # 需要把传进来的字典的value取出来
key_auth = pwd_auth(keep_key) # 再代入函数中
if not key_auth:
print 'Authentication invalid !'
ret = func(*args,**kwargs)
return ret
return inner
@Decorator
def operation(arg):
lis = [11,22,33]
return lis
my_pwd = 'aabbdd'
print operation('test',token=my_pwd)
## Authentication invalid !
## [11, 22, 33]
(7)多个装饰器装饰一个函数
def Decorator(func): # 1、
def inner(*args,**kwargs): # 7、10、
# ...
return func(*args,**kwargs) # 11、
return inner # 8、
def Decorator1(func): # 2、
def inner(*args,**kwargs): # 5、12、
# ...
return func(*args,**kwargs) # 13、
return inner # 6、
@Decorator # 3、14、
@Decorator1 # 4、
def operation(arg1,arg2,arg3): # 15、
print 'operation'
operation('test1','test2','test3') # 9、
## operation
(8)多层装饰器
# 装饰器带参数,而且有多层,参考老师的博客,其实我是迷茫的……
def Before(request,kargs): # 1、函数体加入内存。12、传入实参到函数中
print 'before'
def After(request,kargs): # 2、函数体加入内存。19传入实参到函数中
print 'after'
def Decorator(before_func,after_func): # 3、函数体加入内存。
def outer(main_func): # 5、函数体加入内存。
def wrapper(request,kargs): # 7、函数体加入内存。10、传入实参到函数中
before_result = before_func(request,kargs) # 11、赋值
if(before_result != None): # 13、判断条件,满足则将实参传入wrapper(request,kargs)
return before_result;
main_result = main_func(request,kargs) # 14、赋值
if(main_result != None): # 17、判断条件,满足则将实参传入wrapper(request,kargs)
return main_result;
after_result = after_func(request,kargs) # 18、赋值
if(after_result != None): # 20、判断条件,满足则将实参传入wrapper(request,kargs)
return after_result;
return wrapper # 8、返回函数体
return outer # 6、返回函数体。
@Decorator(Before, After) # 4、调用装饰器。15、再次调用装饰器
def Index(request,kargs): # 9、函数体加入内存。16、传入实参到函数中
print 'index'
Index('aa','bb')
# before
# index
# after
6、递归
斐波那契数列
def func(arg1,arg2):
if arg1 == 0:
print arg1,arg2
arg3 = arg1 + arg2
print arg3
if arg3 > 1000:
return
func(arg2,arg3)
func(0,1)
最后一位的返回值
def func(arg1,arg2):
if arg1 == 0:
pass
arg3 = arg1 + arg2
if arg3 > 1000:
return arg3
return func(arg2,arg3)
print func(0,1)
四、文件操作
五、函数
函数是按功能划分的一组代码块,分内置函数与自定义函数,函数在没有被调用之前不会生效。
A、内置函数
print vars() == 当前模块的所有变量
{'__builtins__': <module '__builtin__' (built-in)>,
'__name__': '__main__', # 主函数
'__file__': '/Users/joliet/Documents/mytest/Hello.py',
'__doc__': None, # 注释内容
'__package__': None}
# 有时会在程序开头声名主函数
if __name__ == '__main__' (主函数)
1、map
遍历序列,对序列中每个元素进行操作,最终获取新的序列。
列表中的每个元素加10
lis = [11,22,33]
m_lis = map(lambda a : a +10 ,lis)
print m_lis
## [21, 32, 43]
两个列表相加
lis1 = [11,22,33]
lis2 = [4,5,6]
m_lis = map(lambda a,b : a + b,lis1,lis2)
print m_lis
## [15, 27, 39]
2、filter
对于序列中的元素进行筛选,最终获取符合条件的序列
lis = [11, 22, 33]
f_lis = filter(lambda arg: arg > 22, lis) # filter第一个参数为空,将获取原来序列
print f_lis
## [33]
3、reduce
对于序列内所有元素进行累计操作
lis = [11, 22, 33]
r_lis = reduce(lambda arg1, arg2: arg1 + arg2, lis)
print r_lis
# 666
# reduce的第一个参数,函数必须要有两个参数
# reduce的第二个参数,要循环的序列
# reduce的第三个参数,初始值
B、自定义函数
1、理解
面向过程编程:在编程过程中会出现大量重复性的代码,按步骤来解决问题。
面向对象编程:对程序、函数进行分类封装,使开发效率更高
函数式编程:将功能代码封装到函数中,不用重复编写,只需调用即可。函数式编程最重要的是增强代码的重用性和可读性
2、定义与使用
def function(params):
block
return expression/value
# def 函数的关键字
# function 函数名
# params 参数
# block 函数体
# return 返回值,如果不指定程式或内容,默认返回None
3、参数
形式参数:形参,未指明具体的值(在内存中未开辟空间)
实际参数:实际,具体的值(在内存中未开辟空间)
(1)普通参数
def func(name): # name:形参,当然参数也可以有多个,可以传入多个值
print name
func('hello') # 'hello':实参
(2)默认参数
def func(name,age = 18): # age = 18便是一个默认参数,当实参不指定值的话则使用默认参数
print "%s:%s" % (name,age)
func('hello')
## hello:18
(3)动态参数
加*
def func(*args):
print args
func(11,22,33,44)
# or
lis = [11,22,33,44]
func(*lis)
## (11, 22, 33, 44)
## (11, 22, 33, 44)
加**
def func(**kwargs):
print kwargs
func(name = 'tom',age = 18)
# or
dic = {'name':'tom','age':18}
func(**dic)
## {'age': 18, 'name': 'tom'}
## {'age': 18, 'name': 'tom'}
加*与**
def func(*args,**kwargs):
print args,kwargs
func(11,22,name = 'tom',age = 18)
# or
dic = {'name':'tom','age':18}
lis = [11,22]
func(*lis,**dic)
## (11, 22) {'age': 18, 'name': 'tom'}
## (11, 22) {'age': 18, 'name': 'tom'}
4、lambda表达式
(1)回想之前学过的三元运算
# 常规的if..else..
if 1 == 1:
name = 'kim'
else:
name = 'tom'
# 三元运算,简化了上面的流程控制语句
name = 'kim' if 1 == 1 else 'tom'
(2)对于简单的函数,也可以用简化的方式来表示。
# 常规函数
def func(arg):
return arg + 1
result =func(100)
# lambda表达式,只对简单的函数简洁表示
func = lambda arg : arg + 1
result = func(100)
5、发邮件实例
import smtplib from email.mime.text import MIMEText from email.utils import formataddr def mail(s): msg = MIMEText('邮件内容', 'plain', 'utf-8') msg['From'] = formataddr(["小明",'aaa@qq.com']) msg['To'] = formataddr(["小红",'aaa@qq.com']) msg['Subject'] = "主题" server = smtplib.SMTP("smtp.126.com", 25) server.login("aaa@qq.com", "邮箱密码") server.sendmail('aaa@qq.com', ['aaa@qq.com',], msg.as_string()) server.quit() if __name__ == '__main__': hua = 100 qing = 150 for i in range(1): if hua > 20: call = 'too old' mail(call) if qing < 180: call = 'too too old' mail(call)