python迭代器和生成器-阿里云开发者社区

开发者社区> 吞吞吐吐的> 正文

python迭代器和生成器

简介:
+关注继续查看

列表推导:

生成一个列表:[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 multitask
from threading import Thread
import time

def conroutine_1():
    for i in range(3):
        print 'c1'
        yield i

def conroutine_2():
    for i in range(3):
        print 'c2'
        yield i

def 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()
复制代码

 

上面的程序运行的结果可能是这样的:

复制代码
==========协同========
c1
c2
c1
c2
c1
c2
==========多线程========
c3
c3c4

c3
c4
c4
复制代码

 

从结果来看,协同程序c1和c2依次执行,多线程的执行结果就不好说了,有多种可能

下面的程序是用生成器形成的echo服务器

复制代码
#!/usr/bin/env python
#coding=utf-8
from __future__ import with_statement
from contextlib import closing
import socket
import multitask
def 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-8
import itertools
def 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 6
5
6
input2: 1 2    
input2: 1 2 3 4 5 6 7 8
5
6
7
8
input2: 
复制代码

 

从上面的例子可以看出,上面的代码是输出第4个之后的元素,利用这个功能我们可以输出特定位置的元素

tee
复制代码
#!/usr/bin/env python
#coding=utf-8
import itertools
def with_head(iterable,headsize=1):
    a, b = itertools.tee(iterable)
    print list(itertools.islice(a,headsize)),b
seq = [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-8
import itertools
def 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

 


本文转自ma6174博客园博客,原文链接:http://www.cnblogs.com/ma6174/archive/2013/01/06/2847563.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
再探迭代器(插入迭代器、流迭代器、反向迭代器、移动迭代器)
除了为每个容器定义的迭代器之外,标准库在头文件iterator中还定义了额外几种迭代器。这些迭代器包括以下几种。 插入迭代器:这些迭代器被绑定到一个容器上,可用来向容器插入元素 流迭代器:这些迭代器被绑定到输入或输出上,可用来遍历所有关联的IO流 反向迭代器:这些迭代器向后而不是向前移动。
736 0
Python——列表生成式
生成列表 生成[1x1, 2x2, 3x3, …, 10x10],方法一: >>> L = [] >>> for x in range(1, 11): ... L.append(x * x) ... >>> L [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 但是使用列表生成式,可以这样写: [x * x for x in range(1, 11)] 一行搞定。
672 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
7748 0
14、C++ Primer 4th 笔记,迭代器
1、三种迭代器 1)插入迭代器(insert iterator):迭代器适配器,与容器绑定在一起,实现在容器中插入元素的功能。形参为一个迭代器和一个指向容器的引用。 • back_inserter,创建使用 push_back 实现插入的迭代器,形参为指向容器的引用的迭代器适配器。
827 0
javascript中的迭代器
1.forEach迭代器 forEach方法接收一个函数作为参数,对数组中每个元素使用这个函数,只调用这个函数,数组本身没有任何变化 //forEach迭代器 function square(num){ document.
704 0
4533
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载