美文网首页
itertools常用方法

itertools常用方法

作者: 这个手刹丶不太灵 | 来源:发表于2018-08-03 09:25 被阅读0次

    interator tips:

    从Python3.4开始,检查对象x是否迭代,最准确的方法是调用iter(x)函数,如果不可迭代,再处理TypeErro异常。这比isinstance(x, abc.iterable)更准确,因为iter(x)函数会考虑到__getitem__方法,而abc.Iterable类不考虑。

    检查对象x是否是迭代器最好的方式是调用isinstance(x, abc.Iterator)

    Iterables vs Iterators

    如果对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。序列都可以迭代,因为实现了__getitem__方法, 而且其参数是从零开始的索引,这种对象也可以迭代。

    迭代器是这样的对象,实现了无参数的__next__方法,返回序列中的下一个元素,如果没有元素了,就抛出StopIteration异常,Python中的迭代器还实现了__iter__方法(必须return self),因此迭代器也可以迭代。

    可迭代对象和迭代器之间的关系:Python从可迭代的对象中获取迭代器。

    generator 生成器

    只要Python函数中的定义体中有yield关键字,该函数就是生成器函数。调用生成器函数,会返回一个生成器对象。也就是说,生成器函数是生成器工厂。

    所有的生成器都是迭代器,因为生成器完全实现了迭代器接口。

    ArithmeticProgression Generator

    def aritprog_gen(begin, step, end=None):
        result = type(begin + step)(begin)
        forever = end is None
        index = 0
        while forever or result < end:
            yield result
            index += 1
            result = begin + step * index
        
    
    import itertools
    gen = itertools.takewhile(lambda n: n < 3, itertools.count(1, .5))
    list(gen)
    
    [1, 1.5, 2.0, 2.5]
    

    Generator Functions n The Standard Library (filter)

    def vowel(c):
        return c.lower() in 'aeiou'
    
    list(itertools.filterfalse(vowel, 'Aardvark')) # filter内置函数的反用
    
    ['r', 'd', 'v', 'r', 'k']
    
    list(itertools.dropwhile(vowel, 'Aardvark')) # 在条件为false之后的第一次, 返回迭代器中剩下来的项
    
    ['r', 'd', 'v', 'a', 'r', 'k']
    
    list(itertools.takewhile(vowel, 'Aardvark')) # 在vowel返回False时停止
    
    ['A', 'a']
    
    list(itertools.compress('Aardvark', (1, 0, 1, 1, 0, 1)))  # 并行比较两个可迭代对象,如果后者元素为True, 产出前者的值
    
    ['A', 'r', 'd', 'a']
    
    list(itertools.islice('Aardvark', 1, 7, 2))  # 产出前者的切片,主要是惰性操作
    
    ['a', 'd', 'a']
    

    Generator Functions (map)

    sample = [5,4,2,8,7,6,3,0,9,1]
    
    list(itertools.accumulate(sample))
    
    [5, 9, 11, 19, 26, 32, 35, 35, 44, 45]
    
    list(itertools.accumulate(sample, min))
    
    [5, 4, 2, 2, 2, 2, 2, 0, 0, 0]
    
    import operator
    list(itertools.accumulate(sample, operator.mul))
    
    [5, 20, 40, 320, 2240, 13440, 40320, 0, 0, 0]
    
    list(map(operator.mul, range(11), [2, 4, 8]))
    
    [0, 4, 16]
    
    list(map(lambda a, b: (a, b), range(11), [2, 4, 8])) # zip built-in  function does
    
    [(0, 2), (1, 4), (2, 8)]
    
    list(itertools.starmap(operator.mul, enumerate('albatroz', 1))) # [operator.mul(*('a', 1))]
    
    ['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz']
    
    list(itertools.starmap(lambda a, b: b/a, enumerate(itertools.accumulate(sample), 1))) # average
    
    [5.0,
     4.5,
     3.6666666666666665,
     4.75,
     5.2,
     5.333333333333333,
     5.0,
     4.375,
     4.888888888888889,
     4.5]
    

    Generator Functions (merging)

    list(itertools.chain('ABC', range(2)))
    
    ['A', 'B', 'C', 0, 1]
    
    list(itertools.chain(enumerate('ABC')))  # 传入一个参数,没什么卵用
    
    [(0, 'A'), (1, 'B'), (2, 'C')]
    
    list(itertools.chain.from_iterable(enumerate('ABC')))
    
    [0, 'A', 1, 'B', 2, 'C']
    
    list(zip('ABC', range(5), [10, 20, 30, 40]))
    
    [('A', 0, 10), ('B', 1, 20), ('C', 2, 30)]
    
    list(itertools.zip_longest('ABC', range(5), fillvalue='?'))
    
    [('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)]
    

    Generator FUnctions (Cartesian)笛卡尔积

    list(itertools.product('ABC', range(2)))
    
    [('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]
    
    suits = 'spades hearts diamonds clubs'.split()
    list(itertools.product('AK', suits))
    
    [('A', 'spades'),
     ('A', 'hearts'),
     ('A', 'diamonds'),
     ('A', 'clubs'),
     ('K', 'spades'),
     ('K', 'hearts'),
     ('K', 'diamonds'),
     ('K', 'clubs')]
    
    list(itertools.product('ABC'))
    
    [('A',), ('B',), ('C',)]
    
    list(itertools.product('ABC', repeat=2))
    
    [('A', 'A'),
     ('A', 'B'),
     ('A', 'C'),
     ('B', 'A'),
     ('B', 'B'),
     ('B', 'C'),
     ('C', 'A'),
     ('C', 'B'),
     ('C', 'C')]
    
    list(itertools.product('AB', range(2), repeat=2))
    
    [('A', 0, 'A', 0),
     ('A', 0, 'A', 1),
     ('A', 0, 'B', 0),
     ('A', 0, 'B', 1),
     ('A', 1, 'A', 0),
     ('A', 1, 'A', 1),
     ('A', 1, 'B', 0),
     ('A', 1, 'B', 1),
     ('B', 0, 'A', 0),
     ('B', 0, 'A', 1),
     ('B', 0, 'B', 0),
     ('B', 0, 'B', 1),
     ('B', 1, 'A', 0),
     ('B', 1, 'A', 1),
     ('B', 1, 'B', 0),
     ('B', 1, 'B', 1)]
    

    一个元素产出多个值

    list(itertools.islice(itertools.count(1, .3), 3))
    
    [1, 1.3, 1.6]
    
    cy = itertools.cycle('ABC')
    next(cy)
    
    'A'
    
    list(itertools.islice(cy, 7))
    
    ['B', 'C', 'A', 'B', 'C', 'A', 'B']
    
    rp = itertools.repeat(7)
    next(rp), next(rp)
    
    (7, 7)
    
    list(itertools.repeat(8, 4))
    
    [8, 8, 8, 8]
    
    list(map(operator.mul, range(11), itertools.repeat(5)))  # 为map函数提供固定参数5
    
    [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
    
    list(itertools.combinations('ABC', 2))
    
    [('A', 'B'), ('A', 'C'), ('B', 'C')]
    
    list(itertools.combinations_with_replacement('ABC', 2))
    
    [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
    
    list(itertools.permutations('ABC', 2))
    
    [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
    

    用于重新排列元素的生成器函数

    list(itertools.groupby('LLLLAAGGG'))
    
    [('L', <itertools._grouper at 0x108ad79e8>),
     ('A', <itertools._grouper at 0x108ad7550>),
     ('G', <itertools._grouper at 0x108ad7978>)]
    
    for char, group in itertools.groupby('LLLLAAGGG'):
        print(char, '->', list(group))
    
    L -> ['L', 'L', 'L', 'L']
    A -> ['A', 'A']
    G -> ['G', 'G', 'G']
    
    animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear', 'bat', 'dolphin', 'shark', 'lion']
    animals.sort(key=len)
    animals
    
    ['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark', 'giraffe', 'dolphin']
    
    for length, group in itertools.groupby(animals, len):
        print(length, '->', list(group))
    
    3 -> ['rat', 'bat']
    4 -> ['duck', 'bear', 'lion']
    5 -> ['eagle', 'shark']
    7 -> ['giraffe', 'dolphin']
    
    for length, group in itertools.groupby(reversed(animals), len):
        print(length, '->', list(group))
    
    7 -> ['dolphin', 'giraffe']
    5 -> ['shark', 'eagle']
    4 -> ['lion', 'bear', 'duck']
    3 -> ['bat', 'rat']
    
    list(itertools.tee('ABC'))
    
    [<itertools._tee at 0x108ad22c8>, <itertools._tee at 0x108ae4cc8>]
    
    g1, g2 = itertools.tee('ABC')
    
    next(g1)
    
    'A'
    
    next(g2)
    
    'A'
    
    next(g2)
    
    'B'
    
    list(g1)
    
    ['B', 'C']
    
    list(zip(*itertools.tee('ABC')))
    
    [('A', 'A'), ('B', 'B'), ('C', 'C')]
    

    New Syntax in Python3.3: yield from

    def chain(*iterables):
        for i in iterables:
            yield from i
    
    list(chain('ABBC', range(3)))
    
    ['A', 'B', 'B', 'C', 0, 1, 2]
    

    yiled from 除了可以代替循环, 还会创建通道,把内层生成器直接与外层生成器的客户端联系起来。把生成器当成协程使用时,这个通道特别重要,不仅能为客户端代码生成值,还能使用客户端代码提供的值。

    Iterable Reducing Functions (可迭代规约函数)

    all([1, 0, 3])
    
    False
    
    all([])
    
    True
    
    any([1, 0, 3])
    
    True
    
    any([])
    
    False
    
    g = (n for n in [0, 0.0, 7, 8])
    any(g)
    
    True
    
    next(g)
    
    8
    

    iter 一个鲜为人知的用法

    传入两个参数,使用常规的函数或任何可调用的对象创建迭代器。第一个参数必须是可调用对象,用于不断调用产出各个值;第二个值是哨符,这个是标记值,当可调用的对象返回这个值时,出发迭代器抛出StropIteration异常

    from random import randint
    def d6():
        return randint(1, 6)
    
    d6_iter = iter(d6, 1)  # 但是不会输出1
    
    for roll in d6_iter:
        print(roll)
    
    3
    4
    2
    

    有个实用的例子,逐行读取文件,直到遇到空行或达文件末尾为止:

    with open('mydata.txt') as fp:
        for line in iter(fp.readline, ''):
            process_line(line)
    

    Iterator vs Generator

    • 从接口上来看,迭代器协议定义了两个方法:__next____iter__。生成器对象实现了这两个方法,因此从这方面来看,所有的生成器都是迭代器。
    • 从实现方式来看,生成器可以用yield或是生成器表达式。
    • 从概念上来说,迭代器用于遍历集合,从中产出元素。生成器可能无需遍历集合就能生成值,如range函数
    def fibonacci():
        a, b = 0, 1
        while True:
            yield a
            a, b = b, a+b
    

    相关文章

      网友评论

          本文标题:itertools常用方法

          本文链接:https://www.haomeiwen.com/subject/kdtyvftx.html