【问题标题】:Printing all results from a Python generator从 Python 生成器打印所有结果
【发布时间】:2019-01-01 16:29:13
【问题描述】:

我制作了一个生成器函数,它使用关键字搜索 csv 文件,如果有什么我想打印结果。如果不一遍又一遍地使用 print(next(gen_results)) 我怎么能做到这一点?

我已经为 stopIteration 尝试了 try-catch 语句,当没有关键字与联系人匹配但我想要更简洁的解决方案时。

def search(keyword, filename):
    f = open(filename, 'r')
    for line in f:
        if keyword in line:
            yield line
    f.close()

the_generator = search('Python', 'contacts.csv')
print(next(the_generator))
print(next(the_generator))  

contacts.csv
Name01, 89888
Name02, 8885445
Name03, 54555
Name04, 55544584
Name05, 55855
Python, 100
BigPi, 444
Python, 101

如果关键字没有联系人,我希望输出是“未找到任何内容”的语句。如果有关键字的联系人,它会输出所有列表。

【问题讨论】:

  • for 循环?列出分解? print( *the_generator,sep="\n")
  • @DavisHerring 在这种情况下.. 更多的是生成器分解,然后是列表分解。请参阅stackoverflow.com/questions/6319612/python-decompose-a-list - 绝对不是列表理解。
  • @PatrickArtner:好的——这似乎被称为“unpacking”,但我可能会说“扩展”以避免与a,b=f() 混淆(我有时又称之为“分解”)。

标签: python python-3.x generator


【解决方案1】:

请试试这个

def search(keyword, filename):
    f = open(filename, 'r')
    for line in f:
        if keyword in line:
            yield line
        else:
            yield 'Nothing Found'
    f.close()

the_generator = search('Python', 'contacts.csv')
for g in the_generator:
    print(g)

'the_generator' 是一个迭代对象,'for' 循环需要一个迭代对象才能运行。程序的输出将:

Nothing Found
Nothing Found
Nothing Found
Nothing Found
Nothing Found
Python, 100 

【讨论】:

  • 这会产生每行而不是每个文件的“未找到”。
【解决方案2】:
def search(keyword, filename):
    f = open(filename, 'r')
    for line in f:
        if keyword in line:
            yield line
    f.close()

the_generator = search('Python', 'contacts.csv')
my_list=list(the_generator)
if not my_list:
    print("Not Found")
for item in my_list:
    print(item.strip())

【讨论】:

  • @DavisHerring 我认为将其保存到列表并检查它是否为空以在列表为空时打印“Nothing Found”一次是一种简单的方法
  • 当然,现在可以了。 (我已经评论了原始版本。)
  • @DavisHerring 对不起。我回答了我得到的并正在尝试我系统中的其余部分。
【解决方案3】:

您可以将“未找到”测试放在生成器本身中:

def search(keyword, lines):
    cnt = 0
    for line in lines:
        if keyword in line:
            cnt += 1
            yield line
    if cnt==0:
        yield "NOT FOUND"

In [166]: txt = """Name01, 89888
     ...: Name02, 8885445
     ...: Name03, 54555
     ...: Name04, 55544584
     ...: Name05, 55855
     ...: Python, 100
     ...: BigPi, 444
     ...: Python, 101
     ...: """.splitlines()
In [167]: for x in search("Python",txt):print(x)
Python, 100
Python, 101
In [168]: for x in search("Foobar",txt):print(x)
NOT FOUND

否则我认为最简单的方法是list 生成器,然后检查一个空列表。生成器机制本身不计算yields 的数量。

【讨论】:

    【解决方案4】:

    有几种方法可以消耗生成器 - unsing next() 只消耗它的(下一个)值。

    生成文件:

    def gen_file():
        with open("contacts.csv","w") as f:
            f.write("""Name01, 89888
    Name02, 8885445
    Name03, 54555
    Name04, 55544584
    Name05, 55855
    Python, 100
    BigPi, 444
    Python, 101
    """)
    

    使用它:

    gen_file()   
    
    def search(keyword, filename="contacts.csv"):
        """Changed to use .. with open() as f: ... style syntax."""
        with open(filename, 'r') as f:
            for line in f:
                if keyword in line:
                    yield line 
    
    
    # consume all of it into a list - you can reuse it
    print("-"*40)
    the_generator = search('Python', 'contacts.csv')
    contacts = list(the_generator)
    print(*contacts, sep="")
    
    
    print("-"*40)
    # decompose the generator directly for printing
    the_generator = search('Python', 'contacts.csv')
    print(*the_generator, sep="" ) 
    
    
    print("-"*40)
    # use a for loop over the generated results
    the_generator = search('Python', 'contacts.csv')
    for li in the_generator:
        print(li, end="") # remove end=\n
    
    
    print("-"*40)
    # using str.join to create the output
    the_generator = search('Python', 'contacts.csv')
    print("".join(the_generator))
    
    
    print("-"*40)
    # loop endlessly until StopIteration is raised
    try:
        while True:
            print(next(the_generator), end="")
    except StopIteration:
        pass
    

    等等。

    输出(多次):

    ----------------------------------------
    Python, 100
    Python, 101
    

    如果您不重复使用生成的值,那么“最好的”可能是print(*the_generator,sep="") 或更明确的:

    # use a for loop over the generated results
    the_generator = search('Python', 'contacts.csv')
    for li in the_generator:
        print(li,end="") # remove end=\n
    

    您可能还想在这里阅读:Using yield from with conditional in python

    【讨论】:

      猜你喜欢
      • 2014-09-24
      • 2021-12-13
      • 1970-01-01
      • 2014-11-08
      • 2018-06-07
      • 2021-04-26
      • 1970-01-01
      • 2022-01-05
      相关资源
      最近更新 更多