цикл for для понимания списка - PullRequest
1 голос
/ 17 марта 2011

Привет всем, У меня есть некоторый код для чтения определенных строк из файла, и я хотел знать, будет ли он работать быстрее в качестве понимания списка или выражения / функции генератора. И если он работает быстрее, как будет выглядеть код? Все еще изучаю Python. Спасибо за вашу помощь

input = open('C:/.../list.txt', 'r')
output = open('C:/.../output.txt', 'w')

x=0

for line in input:
    x = x+1
    if x > 2 and x < 5:
        output.write(line)

файл списка имеет

1
2
3
4
5

вывод в новом файле

3
4

Ответы [ 6 ]

6 голосов
/ 17 марта 2011

Нет необходимости для понимания списка.

output.write(''.join(itertools.islice(inputfile, 2, 4))
2 голосов
/ 17 марта 2011

Если вы хотите сделать это с генератором:

output.writelines(line for line in input if 2 < int(line) < 5)
1 голос
/ 17 марта 2011

Не быстрее, но если вы хотите использовать понимание списка:

    output.writelines([line for (x, line) in enumerate(input) if 1 < x < 4])

Предполагается, что вы используете фактическое количество строк в позиции файла, а не значение чтения в файле (что, судя по вашему назначению x, верно).

0 голосов
/ 18 марта 2011
def copyLines(infname, outfname, lines):
    lines = list(set(lines))   # remove duplicates
    lines.sort(reverse=True)
    with open(infname, 'r') as inf, open(outfname, 'w') as outf:
        try:
            i = 1
            while lines:
                seek = lines.pop()
                while i<seek:
                    inf.next()
                    i += 1
                outf.write(inf.next())
                i += 1
        except StopIteration:  # hit end of file
            pass

def main():
    copyLines('C:/.../list.txt', 'C:/.../output.txt', range(3,5))

if __name__=="__main__":
    main()

Обратите внимание, что это завершится, как только закончится желаемая строка.

0 голосов
/ 17 марта 2011

Лучший способ узнать, что является самым быстрым, - это протестировать его!

В этом коде я предполагаю, что вы заботитесь о значении строки, а не о том, какой номер строки.

import timeit

def test_comprehension():
  input = open('list.txt')
  output = open('output.txt','w')
  [output.write(x) for x in input if int(x) > 2 and int(x) < 5]

def test_forloop():
    input = open('list.txt')
    output = open('output.txt','w')

    for x in input:
        if int(x) > 2 and int(x) < 5:
            output.write(x)

if __name__=='__main__':
    times = 10000

    from timeit import Timer
    t = Timer("test_comprehension()", "from __main__ import test_comprehension")
    print "Comprehension: %s" % t.timeit(times)

    t = Timer("test_forloop()", "from __main__ import test_forloop")
    print "For Loop: %s" % t.timeit(times)

В этом я просто настраиваю пару функций,один, который делает это с пониманием списка, и другой, который делает это как замкнутый круг.Модуль timeit запускает небольшие биты кода указанное вами количество раз, время его выполнения и возвращает время, затраченное на выполнение.Поэтому, если вы запустите приведенный выше код, вы получите что-то вроде следующего:

Понимание: 0.957081079483 Для цикла: 0.956691980362

Достаточно печально, но примерно так же.1010 *

0 голосов
/ 17 марта 2011

Вы спрашивали конкретно о генераторах и о списочном понимании, но в целом есть несколько подходов к решению проблемы.

Версия генератора:

input  = open('input.txt', 'r')
output = open('output.txt', 'w')

def gen() :
    for line in input :
        yield "FOO " + line

for l in gen() :
    output.write(l)

Понимание списка:

output.writelines("FOO " + line for line in input)

Стиль итератора:

class GenClass(object) :
    def __init__(self, _in) :
        self.input = _in

    def __iter__(self):
        return self

    def next(self) :
        line = self.input.readline()
        if len(line) == 0 :
            raise StopIteration
        return "FOO " + line

output.writelines(GenClass(input))

Мысли:

  • Для понимания списка будет все в памяти
  • Для понимания списка будет ограничен объем кода (функции находятся в режиме oneline)
  • Генератор более гибок в кодировании
  • Стиль итератора, дает вам, вероятно, наибольшую гибкость
  • Немного выше стоимость инициализации (объект)
...