通常当我写一些代码时,我会对列表的长度有一个大概的了解。我想如果我真的很努力,我可以在开始时计算出它的正确大小,但这只是我需要处理的很多事情(比如确保最后没有多余的 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 列表来说可能吗?或者我必须使用其他一些数据结构?还是它的想法太随意了?
我真的不明白你为什么要这样做。通过预先分配 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 数组达到某个目的,但是再一次,您所做的任何更改都会比正常情况下执行得慢。