代码之家  ›  专栏  ›  技术社区  ›  Richard Neumann

运行生成器函数而不关心项目的更简单方法

  •  21
  • Richard Neumann  · 技术社区  · 8 年前

    我有一些用例,在这些用例中,我需要运行生成器函数,而不关心生成的项。
    我不能让它们成为非泛型函数,因为在其他用例中,我当然需要生成的值。

    我目前正在使用一个简单的自制函数来耗尽发电机。

    def exhaust(generator):
         for _ in generator:
             pass
    

    我想知道,是否有一种更简单的方法来做到这一点,我错过了?

    编辑 遵循用例:

    def create_tables(fail_silently=True):
        """Create the respective tables."""
    
        for model in MODELS:
            try:
                model.create_table(fail_silently=fail_silently)
            except Exception:
                yield (False, model)
            else:
                yield (True, model)
    

    在某些情况下,我关心错误值和成功值

    for success, table in create_tables():
        if success:
            print('Creation of table {} succeeded.'.format(table))
        else:
            print('Creation of table {} failed.'.format(table), file=stderr)
    

    在某些情况下,我只想“盲目地”运行函数:

    exhaust(create_tables())
    
    4 回复  |  直到 8 年前
        1
  •  25
  •   Moses Koledoye    8 年前

    为此设置for循环可能相对昂贵,请记住 对于 Python中的循环基本上是简单赋值语句的连续执行;你将执行 n (生成器中的项数)分配,之后仅放弃分配目标。

    您可以将发电机馈送至零长度 deque ; 以C速度消耗,不会像使用时那样耗尽内存 list 以及实现迭代器/生成器的其他可调用项:

    from collections import deque
    
    def exhaust(generator):
        deque(generator, maxlen=0)
    

    摘自 consume itertools配方。

        2
  •  6
  •   Max    6 年前

    def exhaust(generator): all(generator)
    

    如果我们可以假设 generator 将始终返回 True (如您的情况,其中2个元素的元组 (success,table) 是真的,即使 success 和 table 两者都是 False ),或: any(generator) 如果它总是回来 假 ,在“最坏的情况下”, all(x or True for x in generator) .

    那么短&很简单,您甚至可能不需要函数!

    关于“为什么?”评论(我不喜欢这些…):在许多情况下,可能需要对发电机排气。举一个例子,这是一种将for循环作为表达式的方法,例如。, any(print(i,x) for i,x in enumerate(S)) -当然还有一些不那么琐碎的例子。

        3
  •  5
  •   mhawke    8 年前

    根据您的用例,很难想象会有足够多的表来创建,您需要考虑性能。

    此外,表的创建将比迭代要昂贵得多。

    因此,在本例中,您已经拥有的for循环似乎是最简单和最具Pythonic的解决方案。

        4
  •  1
  •   abrac JeffUK    5 年前

    你可以有两个函数,每个函数做一件事,并在适当的时间调用适当的函数?

    def create_table(model, fail_silently=True):
        """Create the table."""
        try:
            model.create_table(fail_silently=fail_silently)
        except Exception:
            return (False, model)
        else:
            return (True, model)
    
    def create_tables(MODELS)
        for model in MODELS:
            create_table(model)
            
    def iter_create_tables(MODELS)
       for model in MODELS:
           yield create_table(model)
    

    当您关心返回值时,请执行以下操作:

    for success, table in iter_create_tables(MODELS):
        if success:
            print('Creation of table {} succeeded.'.format(table))
        else:
            print('Creation of table {} failed.'.format(table), file=stderr)
    

    当你不只是做

    create_tables(MODELS)