zoukankan      html  css  js  c++  java
  • 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/

    对文章有啥看法或建议,可以评论或发电子邮件到ma6174@163.com


  • 相关阅读:
    解决类似 /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found 的问题
    qemu vm setup network(ssh) with buildroot
    C: 当字符数组首指针转化成char *指针,sizeof(*ptr)不为array的size
    C 利用strtok, feof 截取字符串
    LINUX C: 获取本地指定网卡的IP地址
    C语言比较好的风格梳理
    perf-perf stat用户层代码分析
    内核调试-perf introduction
    内核调试-ftrace introduction
    【原创】VB6.0应用程序安装包的生成(Setup Factory 9.0制作安装包的方法)
  • 原文地址:https://www.cnblogs.com/ma6174/p/2847563.html
Copyright © 2011-2022 走看看