.append()耗时吗?

时间:2011-08-23 21:17:26

标签: python append readlines

这些天我一直在操纵大量的文本文件。有时我需要删除行。 我的做法如下:

f=open('txt','r').readlines()
list=[]
for line in f:
    if blablablabla:
       list.append(line)

我知道对于大文件,.readlines()是速率限制步骤,但是.append()步骤呢?在readlines之后追加会花费多少额外的时间吗? 如果是这样,也许我应该找到直接删除我不想要的行的方法,而不是追加我想要的行。

THX

5 个答案:

答案 0 :(得分:5)

如果您以后要过滤它,为什么要使用readlines()读取整个文件?只需迭代它就可以保存想要保留的行。您可以使用列表推导将其减少到几行:

with open('txt', 'r') as f:
    myList = [ line for line in f if blablablabla ]

答案 1 :(得分:2)

作为一般提示,请执行此操作,在迭代之前无需先读取完整文件...

with open('txt') as fd:
    for line in fd:
        if blablabla:
            my_list.append(line)

并且不要调用列表“列表”......

答案 2 :(得分:1)

你应该使用列表理解,就像杰夫的回答一样。根据您处理数据的方式,您可以使用生成器表达式。

回答有关append()

的问题

Python列表最后预先分配了一些额外的空间。这意味着追加非常快 - 直到你用完预分配的空间。无论何时扩展列表,都会分配一个新的内存块,并将所有引用复制到它。随着列表的增长,额外预分配空间的大小也会增加。这样做是为了使追加摊销O(1)。即追加的平均时间是快速且恒定的

答案 3 :(得分:1)

在这篇文章中,我尝试解释列表的工作方式以及为什么追加不是非常昂贵的。我还在底部发布了一个可用于删除行的解决方案。

Python列表的结构就像一个节点网络:

>>> class ListItem:
        def __init__(self, value, next=None):
            self.value = value
            self.next = next
        def __repr__(self):
            return "Item: %s"%self.value


>>> ListItem("a", ListItem("b", ListItem("c")))
Item: a
>>> mylist = ListItem("a", ListItem("b", ListItem("c")))
>>> mylist.next.next
Item: c

因此,追加基本上就是这样:

ListItem(mynewvalue, oldlistitem)

附加没有太多开销,但另一方面insert()要求您重建整个列表,因此需要更多时间。

>>> from timeit import timeit
>>> timeit('a=[]\nfor i in range(100): a.append(i)', number=1000)
0.03651859015577941
>>> timeit('a=[]\nfor i in range(100): a.insert(0, i)', number=1000)
0.047090002177625934
>>> timeit('a=[]\nfor i in range(100): a.append(i)', number=10000)
0.18015429656996673
>>> timeit('a=[]\nfor i in range(100): a.insert(0, i)', number=10000)
0.35550057300308424

如您所见,插入速度要慢得多。如果我是你,我只需消除你不需要的行,立即写回来。

with open("large.txt", "r") as fin:
    with open("large.txt", "w") as f:
        for line in fin:
            if myfancyconditionismet:
                # write the line to the file again
                f.write(line + "\n")
            # otherwise it is gone

有我的解释和解决方案。

-Sunjay03

答案 4 :(得分:0)

也许你想把它全部拉进内存然后对它进行操作。也许一次操作一行更有意义。从你的解释中可以看出哪个更好。

无论如何,无论您采用哪种方法,这都是非常标准的代码:

# Pull one line into memory at a time
with open('txt','r') as f:
    lineiter = (line for line in f if blablablabla)
    for line in lineiter:
        # Do stuff

# Read the whole file into memory then work on it
with open('txt','r') as f:
    lineiter = (line for line in f if blablablabla)
    mylines = [line for line in lineiter]

如果您选择前一条路线,我建议您阅读发电机。 Dave Beazley有一篇关于生成器的文章"Generator Tricks for Systems Programmers"。强烈推荐。