zoukankan      html  css  js  c++  java
  • 标准库中的生成器函数

    用于过滤的生成器函数

    1、itertools.compress(it, selector_it)

    并行处理两个可迭代对象;如果select_it中的元素是真值,产出it中对应的元素

    2、itertools.dropwhile(predicate, it)

    处理it,跳过predicate的计算结果为真值的元素,然后产出剩下的各个元素

    3、filter(predicate, it)

    把it中的各个元素传给predicate,如果predicate(item)返回真值,那么产生对应的元素;如果predicate是None,那么只产出真值元素。

    4、itertools.filterfalse(predicate, it)

    与filter函数的作用类似,不过predicate的逻辑是相反的,predicate返回假值时产生对应的元素

    5、itertools.islice(it, stop)或islice(it, start, stop, step=1)

    产出的it切片,作用类似于s[: stop]或s[start: stop: step],不过it可以是任何可迭代的对象,而且这个函数实现的是惰性操作

    6、itertools.takewhile(predicate, it)

    predicate返回真值时产出对应的元素,然后立刻停止,不再继续检查

     1 def vowel(c):
     2     return c.lower() in 'aeiou'
     3 
     4 
     5 print(list(filter(vowel, 'Aardvark')))
     6 # ['A', 'a', 'a']
     7 import itertools
     8 
     9 print(list(itertools.filterfalse(vowel, 'Aardvark')))
    10 # ['r', 'd', 'v', 'r', 'k']
    11 print(list(itertools.dropwhile(vowel, 'Aardvark')))
    12 # ['r', 'd', 'v', 'a', 'r', 'k']
    13 print(list(itertools.takewhile(vowel, 'Aardvark')))
    14 # ['A', 'a']
    15 print(list(itertools.islice('Aardvark', 4)))
    16 # ['A', 'a', 'r', 'd']
    17 print(list(itertools.islice('Aardvark', 4, 7)))
    18 # ['v', 'a', 'r']
    19 print(list(itertools.islice('Aardvark', 1, 7, 2)))
    20 # ['a', 'd', 'a']
    测试代码

    用于映射的生成器函数

    1、itertools.accumulate(it, [func])

    默认产出累积的总和,如果提供了func,那么把前两个元素传给它,然后把计算结果和下一个元素传给它,以此类推,最后产出结果

    2、enumerate(iterable, start=0)

    产生由两个元素组成的元组,结构是(index, item),其中index从start开始计数,item则从iterable中获取

    3、map(func, it1, [it2, ..., itN])

    把it中的各个元素传给func,产出结果;如果传入N个可迭代的对象,那么func必须接收N个参数,而且要并行处理各个可迭代对象

    4、itertools.starmap(func, it)

    把it中的各个元素传给func,产出结果;输入的可迭代对象应该产出可迭代的元素iit,然后以func(*iit)这种形态调用func

     1 sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
     2 
     3 import itertools
     4 
     5 print(list(itertools.accumulate(sample)))
     6 # [5, 9, 11, 19, 26, 32, 35, 35, 44, 45]
     7 print(list(itertools.accumulate(sample, min)))
     8 # [5, 4, 2, 2, 2, 2, 2, 0, 0, 0]
     9 print(list(itertools.accumulate(sample, max)))
    10 # [5, 5, 5, 8, 8, 8, 8, 8, 9, 9]
    11 
    12 import operator
    13 print(list(itertools.accumulate(sample, operator.mul)))
    14 # [5, 20, 40, 320, 2240, 13440, 40320, 0, 0, 0]
    15 print(list(itertools.accumulate(range(1, 11), operator.mul)))
    16 # [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
    accumulate生成器函数
     1 print(list(enumerate('albatroz', 1)))
     2 # [(1, 'a'), (2, 'l'), (3, 'b'), (4, 'a'), (5, 't'), (6, 'r'), (7, 'o'), (8, 'z')]
     3 import operator
     4 
     5 print(list(map(operator.mul, range(11), range(11))))
     6 # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
     7 print(list(map(operator.mul, range(11), [2, 4, 8])))
     8 # [0, 4, 16]
     9 print(list(map(lambda a, b: (a, b), range(11), [2, 4, 8])))
    10 # [(0, 2), (1, 4), (2, 8)]
    11 import itertools
    12 
    13 print(list(itertools.starmap(operator.mul, enumerate('albatroz', 1))))
    14 # ['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz']
    15 sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
    16 
    17 print(list(itertools.starmap(lambda a, b: b/a, enumerate(itertools.accumulate(sample), 1))))
    18 # [5.0, 4.5, 3.6666666666666665, 4.75, 5.2, 5.333333333333333, 5.0, 4.375, 4.888888888888889, 4.5]
    测试代码

    合并多个可迭代对象的生成器函数

    1、itertools.chain(it1, ..., itN)

    先产出it1中的所有元素,然后产生it2中的所有元素,以此类推,无缝连接在一起

    2、itertools.chain.from_iterable(it)

    产生it生成的各个可迭代对象中的元素,一个接一个,无缝连接在一起;it应该产出可迭代的元素,列入可迭代的对象列表

    3、itertools.product(it1, ..., itN, repeat=1)

    计算笛卡尔积:从输入的各个可迭代对象中获取元素,产出由N个元素组成的元组,与嵌套的for循环效果一样;repeat指明重复处理多少次输入的可迭代对象

    4、zip(it1, ..., itN)

    并行从输入的各个可迭代对象中获取元素,产出由N个元素组成的元组,只要有一个可迭代的对象到头了,就默默地停止。

    5、itertools.zip_longest(it1, itN, fillvalue=None)

    并行从输入的各个可迭代对象中获取元素,产出N个元素组成的元组,等到最长的可迭代对象到头后停止,空缺的值使用fillvalue填充

     1 import itertools
     2 print(list(itertools.chain('ABC', range(2))))
     3 # ['A', 'B', 'C', 0, 1]
     4 print(list(itertools.chain(enumerate('ABC'))))
     5 # [(0, 'A'), (1, 'B'), (2, 'C')]
     6 print(list(itertools.chain.from_iterable(enumerate('ABC'))))
     7 # [0, 'A', 1, 'B', 2, 'C']
     8 print(list(zip('ABC', range(5))))
     9 # [('A', 0), ('B', 1), ('C', 2)]
    10 print(list(zip('ABC', range(5), [10, 20, 30, 40])))
    11 # [('A', 0, 10), ('B', 1, 20), ('C', 2, 30)]
    12 print(list(itertools.zip_longest('ABC', range(5))))
    13 # [('A', 0), ('B', 1), ('C', 2), (None, 3), (None, 4)]
    14 print(list(itertools.zip_longest('ABC', range(5), fillvalue='?')))
    15 # [('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)]
    演示用于合并的生成器函数
     1 import itertools
     2 
     3 print(list(itertools.product('ABC', range(2))))
     4 # [('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]
     5 suits = 'spades hearts diamonds clubs'.split()
     6 
     7 print(list(itertools.product('AK', suits)))
     8 # [('A', 'spades'), ('A', 'hearts'), ('A', 'diamonds'), ('A', 'clubs'), ('K', 'spades'), ('K', 'hearts'), ('K', 'diamonds'), ('K', 'clubs')]
     9 print(list(itertools.product('ABC')))
    10 # [('A',), ('B',), ('C',)]
    11 print(list(itertools.product('ABC', repeat=2)))
    12 # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
    13 print(list(itertools.product(range(2), repeat=3)))
    14 # [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
    15 rows = itertools.product(range(2), repeat=3)
    16 
    17 for row in rows:
    18     print(row)
    19 # (0, 0, 0)
    20 # (0, 0, 1)
    21 # (0, 1, 0)
    22 # (0, 1, 1)
    23 # (1, 0, 0)
    24 # (1, 0, 1)
    25 # (1, 1, 0)
    26 # (1, 1, 1)
    product生成器函数

    把输入的各个元素扩展成多个输出元素的生成器函数

    1、itertools.combinations(it, out_len)

    把it产生的out_len个元素组合在一起,然后产出

    2、itertools.combinations_with_replacement(it, out_len)

    把it产出的out_len个元素组合在一起,然后产出包含相同元素的组合

    3、itertools.count(start=0, step=1)

    从start开始不断产出数字,按step指定的步幅增加

    4、itertools.cycle(it)

    从it中产出各个元素,村粗各个元素的副本,然后按顺序重复不断地产出各个元素

    5、itertools.permutations(it, out_len=None)

    把out_len个it产出的元素排列到一起,然后产出这些排列;out_len的默认值等于len(list(it))

    6、itertools.repeat(item, [times])

    重复不断地产出指定的元素,除非提供times,指定次数

     1 import itertools, operator
     2 
     3 
     4 ct = itertools.count()
     5 print(next(ct))
     6 # 0
     7 print(next(ct), next(ct), next(ct))
     8 # 1 2 3
     9 print(list(itertools.islice(itertools.count(1, .3), 3)))
    10 # [1, 1.3, 1.6]
    11 cy = itertools.cycle('ABC')
    12 print(next(cy))
    13 # A
    14 print(list(itertools.islice(cy, 7)))
    15 # ['B', 'C', 'A', 'B', 'C', 'A', 'B']
    16 rp = itertools.repeat(7)
    17 print(next(rp), next(rp))
    18 # 7 7
    19 print(list(itertools.repeat(8, 4)))
    20 # [8, 8, 8, 8]
    21 print(list(map(operator.mul, range(11), itertools.repeat(5))))
    22 # [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
    count、repeat和cycle的用法
     1 import itertools
     2 
     3 print(list(itertools.combinations('ABC', 2)))
     4 # [('A', 'B'), ('A', 'C'), ('B', 'C')]
     5 print(list(itertools.combinations_with_replacement('ABC', 2)))
     6 # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
     7 print(list(itertools.permutations('ABC', 2)))
     8 # [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
     9 print(list(itertools.product('ABC',repeat=2)))
    10 # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
    组合学生成器函数会输入的各个元素中产生多个值

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

    1、itertools.groupby(it, key=None)

    产生由两个元素组成的元素,形式为(key, group),其中可以是分组标准,group是生成器,用于产出分组里的元素

    2、reversed(seq)

    从后往前,倒序产出seq中的元素;seq必须是序列,或者是实现了__reversed__特殊方法的对象

    3、itertools.tee(it, n=2)

    产出一个由n个生成器组成的元组,每个生成器用于单独产出输入的可迭代对象中的元素

     1 import itertools
     2 
     3 print(list(itertools.groupby('LLLLAAGGG')))
     4 # [('L', <itertools._grouper object at 0x10dcf2208>), 
     5 # ('A', <itertools._grouper object at 0x10dcf2240>), 
     6 # ('G', <itertools._grouper object at 0x10dcf2198>)]
     7 
     8 for char, group in itertools.groupby('LLLLAAGGG'):
     9     print(char, '-->', list(group))
    10 # L --> ['L', 'L', 'L', 'L']
    11 # A --> ['A', 'A']
    12 # G --> ['G', 'G', 'G']
    13 
    14 animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear', 'bat', 'dolphin', 'shark', 'lion']
    15 animals.sort(key=len)
    16 print(animals)
    17 # ['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark', 'giraffe', 'dolphin']
    18 
    19 for length, group in itertools.groupby(animals, len):
    20     print(length, '-->', list(group))
    21 # 3 --> ['rat', 'bat']
    22 # 4 --> ['duck', 'bear', 'lion']
    23 # 5 --> ['eagle', 'shark']
    24 # 7 --> ['giraffe', 'dolphin']
    25 
    26 for length, group in itertools.groupby(reversed(animals), len):
    27     print(length, '-->', list(group))
    28 # 7 --> ['dolphin', 'giraffe']
    29 # 5 --> ['shark', 'eagle']
    30 # 4 --> ['lion', 'bear', 'duck']
    31 # 3 --> ['bat', 'rat']
    groupby函数用法
     1 import itertools
     2 
     3 print(itertools.tee('ABC'))
     4 # (<itertools._tee object at 0x10dd1e8c8>, 
     5 # <itertools._tee object at 0x10dd1e908>)
     6 
     7 g1, g2 = itertools.tee('ABC')
     8 
     9 print(next(g1))
    10 # A
    11 print(next(g2))
    12 # A
    13 print(next(g2))
    14 # B
    15 print(list(g1))
    16 # ['B', 'C']
    17 print(list(zip(*itertools.tee('ABC'))))
    18 # [('A', 'A'), ('B', 'B'), ('C', 'C')]
    tee函数的用法

    yield from

    场景:如果生成器函数需要产出另一个生成器生成的值,传统的解决方法是使用嵌套的for循环

     1 def chain(*iterables):
     2     for it in iterables:
     3         for i in it:
     4             yield i
     5 
     6 
     7 s = 'ABC'
     8 t = tuple(range(3))
     9 print(list(chain(s, t)))
    10 # ['A', 'B', 'C', 0, 1, 2]
    传统写法
    1 def chain_new(*iterables):
    2     for i in iterables:
    3         yield from i
    4 
    5 s = 'ABC'
    6 t = tuple(range(3))
    7 print(list(chain(s, t)))
    8 # ['A', 'B', 'C', 0, 1, 2]
    yield from的新句法

    可以看出yield from i完全替代了内层的for循环。在这个示例中使用yield from是对的,而且代码读起来更顺畅,感觉更像是语法糖。除了代替循环之外,yield from还会创建通道,把内层生成器直接与外层生成器的客户端联系起来。把生成器当成协程使用时,这个通道特别重要,不仅能为客户端生成值,还能使用客户端代码提供的值。

    最值得注意的几个函数

    islice: 允许对一个无穷生成器进行切片

    chain: 将多个生成器链接到一起

    takewhile: 给生成器添加一个终止条件

    cycle: 通过不断重复将一个有穷生成器变成无穷

  • 相关阅读:
    LUA脚本中的方法使用冒号和点,以及调用者使用冒号和点
    Lua类对象的继承
    Lua类对象和类对象的单例
    toLua使用protobuf协议转Lua表
    关于Lua表的弱引用
    Lua-面向对象中函数使用时冒号(:)和点(.)的区别
    Python【day 14-5】sorted filter map函数应用和练习
    Python【day 14-4】sorted filter map+递归文件夹+二分法查找
    Python【day 14-3】二分法查找
    Python【day 14-2】递归遍历文件夹
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/10427201.html
Copyright © 2011-2022 走看看