简体   繁体   English

从Python生成器打印所有结果

[英]Printing all results from a Python generator

I have made a generator function which search a csv file using a keyword and I want to print the results if there is something. 我已经做了一个生成器函数,可以使用关键字搜索一个csv文件,如果有的话我想打印结果。 How can I do that without using the print(next(gen_results)) over and over again? 我如何才能做到一遍又一遍不使用print(next(gen_results))?

I have tried a try-catch statement for the stopIteration, when there is no matching of keyword with a contact but I want a more concise solution. 当关键字与联系人不匹配时,我尝试了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

I expect the output to be a statement as 'Nothing Found',if there are no contacts with the keyword. 如果没有与关键字的联系,我希望输出为“ Nothing Found”的语句。 In case there are contacts with the keyword, it outputs all the listings. 如果有使用该关键字的联系人,它将输出所有列表。

Please try this 请尝试这个

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' is an iterate object and 'for' loop needs an iterate object to run. “ the_generator”是一个迭代对象,“ for”循环需要一个迭代对象才能运行。 The output of the program will : 该程序的输出将:

Nothing Found
Nothing Found
Nothing Found
Nothing Found
Nothing Found
Python, 100 
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())

You could put the 'not found' test in the generator itself: 您可以将“未找到”测试放入生成器本身:

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

Otherwise I think the simplest is to list the generator, and check for an empty list. 否则,我认为最简单的方法是list生成器,并检查一个空列表。 By itself the generator mechanism does not count the number of yields . 就其本身而言,生成器机制不计算yields的数量。

There are several methods to consume the generator - unsing next() only consumes (the next) value of it. 有几种消耗生成器的方法-取消调用next()仅消耗生成器的(下一个)值。

Generate file: 生成文件:

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
""")

Use it: 用它:

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

etc. 等等

Output (several times): 输出(几次):

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

The "best" one if you do not reuse the generated values is probably print(*the_generator,sep="") or the more explicit: 如果您不重用生成的值,则“最佳”方法可能是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

You may also want to read here: Using yield from with conditional in python 您可能还想在这里阅读: 在Python中使用带有条件的yield from

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM