与使用 2 个文本文件的双循环相比,使用 2 个列表的双循环 - 不同的结果

Double for Loop Using 2 Lists Compared to Double Loop Using 2 Text Files - Different Outcome

所以我有 2 个迷你脚本。 1 产生我期望的输出,另一个没有。产生我预期的输出的第一个代码:

with open('cities.txt', 'r') as cities, \
    open('test_file.txt', 'r') as test:
    space = " "
    city_lst = []
    test_lst = []
    for c in cities:
        city_lst.append(c)
    for t in test:
        test_lst.append(t)
    for city in city_lst:
        for tes in test_lst:
            print city.rstrip(),space,tes.rstrip() 

输出(如我所料):

san diego   san diego is the best place
san diego   Then there is new york state
san diego   And now we have tuscon in arizona
san francisco   san diego is the best place
san francisco   Then there is new york state
san francisco   And now we have tuscon in arizona
tuscon   san diego is the best place
tuscon   Then there is new york state
tuscon   And now we have tuscon in arizona
pheonix   san diego is the best place
pheonix   Then there is new york state
pheonix   And now we have tuscon in arizona
sedona   san diego is the best place
sedona   Then there is new york state
sedona   And now we have tuscon in arizona
baton rouge   san diego is the best place
baton rouge   Then there is new york state
baton rouge   And now we have tuscon in arizona

在下一段代码中,我没有得到我想要的输出。它与上面的代码基本相同,只是我直接使用文本文件而不是先将它们转换为列表。但是,令我困惑的是为什么我没有得到完全相同的输出。

代码:

with open('cities.txt', 'r') as cities, \
    open('test_file.txt', 'r') as test:
    space = " "
    for c in cities:
        for t in test:
            print c.rstrip(), space, t.rstrip()

输出:

san diego   san diego is the best place
san diego   Then there is new york state
san diego   And now we have tuscon in arizona

因为我在每个代码中都使用相同的 double for 循环,使用相同的 print 语句,为什么输出有差异?

以下是文本文件的内容: cities.txt:

san diego
san francisco
tuscon
pheonix
sedona
baton rouge

test_file.txt:

san diego is the best place
Then there is new york state
And now we have tuscon in arizona

因为文件是迭代器,而列表就是列表。

当你做的时候

for t in test:
    pass # do anything here

到该循环结束时,您已经用完了迭代器。里面什么都没有了!自己试试吧!:

with open('testfile.txt') as inf:
    for line in inf:
        print("There's a line here, I'm reading!")
    for line in inf:
        print("Turn lead into gold")

你会发现这里完全没有炼金术。

您可以做的是在每次读取文件之前seek回到文件的开头。

for c in cities:
    test.seek(0)
    # place the pointer at the beginning of the file
    for t in test:
        frobnicate_stuff()

不过,我更喜欢读取每个文件一次并对列表进行操作,就像您在上面的示例中所做的那样。你可以用 itertools.product:

做得更好
import itertools

with open('cities.txt') as cities, \
         open('test.txt') as test:
    city_lst = cities.readlines()
    test_lst = test.readlines()

for c, t in itertools.product(city_lst, test_lst):
    print(c.rstrip() + " " + t.rstrip())
    # or using string formatting:
    # # print("{} {}".format(c.rstrip(), t.rstrip()))

编辑

事实上,进一步的测试表明 itertools.product 在使用每个迭代器之前将其内部化!这意味着我们可以做:

with open('cities.txt') as cities, \
        open('tests.txt') as tests:
    for c, t in itertools.product(cities, tests):
        print(c.rstrip() + " " + t.rstrip())

因为文件的对象是迭代器。要将其转换为列表,请使用 .readlines() 函数。你的代码应该是这样的:

with open('cities.txt') as cities, open('tests.txt') as tests:
    for c in cities.readlines()
        for t in tests.readlines():
            print(c.rstrip() + " " + t.rstrip())

或者,您也可以使用 itertools.product() 来防止嵌套循环。在这种情况下,您的代码应该是这样的:

with open('cities.txt') as cities, open('tests.txt') as tests:
    for c, t in itertools.product(cities.readlines(), tests.readlines()):
        print("{city} {test}".format(city=c,test=t))

注意:不要使用 + 直接附加字符串。使用 .format() 方法更好。