文章目錄
- 列表推導:
- enumerate
- 迭代器:
- 產生器
- 協同程式
- itertools模組
列表推導:
產生一個列表:[0,2,4,6,8]
>>> [i for i in range(10) if i % 2 == 0][0,2,4,6,8]
enumerate
seq = ["one","two","three"]for i,element in enumerate(seq): seq[i] = '%d:%s' % (i,seq[i])
上面的代碼將產生下面的列表: ['0:one','1:two','2:three']
迭代器:
>>> i = iter('abc')>>> i.next()'a'>>> i.next()'b'>>> i.next()'c'>>> i.next()Traceback (most recent call last): File "<stdin>", line 1, in <module>StopIteration>>>
遍曆完畢將產生 StopIteration 異常
產生器
>>> def fibonacci():... a, b = 0, 1... while True:... yield b... a, b = b, a+b... >>> fib = fibonacci()>>> fib.next()1>>> fib.next()1>>> fib.next()2>>> [fib.next() for i in range(10)][3, 5, 8, 13, 21, 34, 55, 89, 144, 233]>>>
協同程式
協同不同於多線程,線程是搶佔式的,下面的例子可以說明這點:
#!/usr/bin/env python#coding=utf-8#協同import multitaskfrom threading import Threadimport timedef conroutine_1(): for i in range(3): print 'c1' yield idef conroutine_2(): for i in range(3): print 'c2' yield idef conroutine_3(): for i in range(3): print 'c3'def conroutine_4(): for i in range(3): print 'c4'print "==========協同========"multitask.add(conroutine_1())multitask.add(conroutine_2())multitask.run()print "==========多線程========"a = Thread(target=conroutine_3,args=())b = Thread(target=conroutine_4,args=())a.start()b.start()
上面的程式啟動並執行結果可能是這樣的:
==========協同========c1c2c1c2c1c2==========多線程========c3c3c4c3c4c4
從結果來看,協同程式c1和c2依次執行,多線程的執行結果就不好說了,有多種可能
下面的程式是用產生器形成的echo伺服器
#!/usr/bin/env python#coding=utf-8from __future__ import with_statementfrom contextlib import closingimport socketimport multitaskdef client_handler(sock): with closing(socket): while True: data = (yield multitask.recv(sock,1024)) if not data: break yield multitask.send(sock,data)def echo_server(hostname,port): addrinfo = socket.getaddrinfo(hostname,port, socket.AF_UNSPEC, socket.SOCK_STREAM) (family,socktype,proto, canonname,sockaddr)=addrinfo[0] with closing(socket.socket(family,socktype,proto)) as sock: sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sock.bind(sockaddr) sock.listen(5) while True: multitask.add(client_handler((yield multitask.accept(sock))[0]))if __name__=='__main__': hostname = 'localhost' port = 1111 multitask.add(echo_server(hostname,port)) try: multitask.run() except KeyboardInterrupt: pass
上面的代碼理解起來有點難度,我也有些地方不太懂,測試的話可以用telnet,方法是:
telnet localhost 1111
然後再輸入一些資訊,斷行符號以後會顯示你發送的資訊。
itertools模組islice:視窗迭代器
#!/usr/bin/env python#coding=utf-8import itertoolsdef starting_at_five(): value = raw_input("input1").strip() while value != '': for el in itertools.islice(value.split(),4,None): yield el value = raw_input("input2").strip()iter = starting_at_five()while True: print iter.next()
下面是一些測試輸入輸出:
input1: 1 2 3 4 5 656input2: 1 2 input2: 1 2 3 4 5 6 7 85678input2:
從上面的例子可以看出,上面的代碼是輸出第4個之後的元素,利用這個功能我們可以輸出特定位置的元素
tee
#!/usr/bin/env python#coding=utf-8import itertoolsdef with_head(iterable,headsize=1): a, b = itertools.tee(iterable) print list(itertools.islice(a,headsize)),bseq = [1]with_head(seq)seq = [1,2,3,4]with_head(seq,4)
上面的代碼我也沒看懂,具體怎麼用還需要進一步學習
代碼運行結果是:
[1] <itertools.tee object at 0xb71f866c>[1, 2, 3, 4] <itertools.tee object at 0xb71f862c>
uniq迭代器:
使用行程長度編碼來壓縮資料:將字串中每組相鄰的重複字元替換成字元本身的重複字數,沒重複則為1,代碼實現:
#!/usr/bin/env python#coding=utf-8import itertoolsdef compress(data): return ((len(list(group)),name) for name,group in itertools.groupby(data))def decompress(data): return (car * size for size,car in data)print list(compress('aaasdffffffffffffffffffffff'))compressed = list(compress('aaasdffffffffffffffffffffff'))print "".join(decompress(compressed))
運行結果:
[(3, 'a'), (1, 's'), (1, 'd'), (22, 'f')]aaasdffffffffffffffffffffff