有线问题,我可以预先分配一个具有一定大小的列表,然后使用 append 方法填充它吗?

问题描述 投票:0回答:1

通常当我写一些代码时,我会对列表的长度有一个大概的了解。我想如果我真的很努力,我可以在开始时计算出它的正确大小,但这只是我需要处理的很多事情(比如确保最后没有多余的 None 会把事情搞砸,或者确保我以后不会索引超出范围)。

看来我必须选择预先分配一些内存并将其索引。或者只是创建一个空白空间并使用 list.append() 方法来填充我的列表。 像这样:

A = [None]*1000
for i in range(1000):
    A[i] = 1

或者这个:

B = []
for i in range(1000):
    B.append(1)

我的问题是有一些中间方法吗?就像我可以做一些事情,比如将大约 1000 个内存单元预分配给一个列表,但是当我追加它时,它会在最后一个带有实际项目的单元格之后添加,而不是在我设置为 None 的单元格之后添加。

想法是这样的(但这实际上行不通):

A = [None]*1000
for i in range(1000):
    A.append(1)

这对 python 列表来说可能吗?或者我必须使用其他一些数据结构?还是它的想法太随意了?

python memory-management processing-efficiency
1个回答
0
投票

我真的不明白你为什么要这样做。通过预先分配 1000 个元素,您不太可能在性能方面获得任何收益,但您可以按照以下方式创建用户定义的类:

from typing import Any

class FixedSizeList:
    def __init__(self, size: int, default_val: Any):
        self._val = [default_val for _ in range(size)]
        self._non_default_idx = 0
        
    def append(self, value: Any):
        self._val[self._non_default_idx] = value
        self._non_default_idx += 1
    
    def extend(self, value: list[Any]):
        self._val[self._non_default_idx: self._non_default_idx + len(value)] = value
        self._non_default_idx += len(value)
        
    def __str__(self):
        return self._val.__str__()

然后你可以像这样使用它:

f = FixedSizeList(10, None)
print(f)         # [None, None, None, None, None, None, None, None, None, None]

f.append(1)
print(f)         # [1, None, None, None, None, None, None, None, None, None]

f.extend([1, 2, 3])
print(f)         # [1, 1, 2, 3, None, None, None, None, None, None]

最终结果可能会慢得多,因为基本列表在引擎盖下使用 C 并且对正常行为的任何更改实际上都会降低性能:

from timeit import timeit

t1 = """
f1 = FixedSizeList(1000, None)
for i in range(1000):
    f1.append(i)
"""

t2 = """
f2 = []
for i in range(1000):
    f2.append(i)
"""

print(timeit(t1, globals=globals(), number=10000))    # 2.07
print(timeit(t2, globals=globals(), number=10000))    # 0.50

您可能会通过扩展 numpy 数组达到某个目的,但是再一次,您所做的任何更改都会比正常情况下执行得慢。

© www.soinside.com 2019 - 2024. All rights reserved.