python - 如何在 Python 中捕获对列表项的直接引用以提高速度?

标签 python list object optimization micro-optimization

在 Python 中,我能否获得对列表中某一项的值的某种直接引用,例如 my_list[0][0]

我正在使用 Python 3.7.2。

这:direct = my_list[0][0] 不起作用;虽然它们最初都指向同一个对象,但当 my_list[0][0] 发生更改时,Python 会更改列表对象。 direct 指向具有旧值的原始对象,my_list[0][0] 指向具有新值的新对象。我正在寻找一种方法,即使在值更改后也能直接指向 my_list[0][0] 中的值,而不必调用调用 my_list[0 的开销][0]。 (列表可能无法实现?)

确认上述内容的代码:

my_list = [[0, 1],
        [0, 1]]

direct = my_list[0][0]

print(id(direct))
print(direct)
print(id(my_list[0][0]))
print(my_list[0][0])

my_list[0][0] = 10

print(id(direct))
print(direct)
print(id(my_list[0][0]))
print(my_list[0][0])

输出:

140706382385952
0
140706382385952
0
140706382385952
0
140706382386272
10

为什么要关心?速度。

我正在优化将数据存储在嵌套列表中的模拟。 这些列表很少被访问,除了一项:my_list[0][0]。这是确定模拟流程的关键项目,因此检查非常频繁。

一些测试代码表明检查这个嵌套列表项的值比直接变量检查花费的时间长 1.6 倍。由于频率,这是运行时间的主要因素。

测试代码:

import time

my_list = [[0, 1],
        [0, 1]]
iterations = 100000000

before = time.time()
for i in range (iterations):
    if my_list[0][0] == 1 : break
after=time.time()

list_time = after - before
print("List check time: "+str(list_time))

before = time.time()
direct = my_list[0][0]
for i in range (iterations):
    if direct == 1 : break
after=time.time()

direct_time = after - before
print("Direct check time: "+str(direct_time))

print("Multiple: "+str(list_time/direct_time))

输出:

List check time: 13.461313247680664
Direct check time: 8.034856081008911
Multiple: 1.6753645755395248

更新:user2357112建议捕获对 my_list[0] 的子列表引用;如果零级列表分配没有改变(在我的例子中,它没有改变),我可以引用 sub_list[0],进行单次取消引用而不是双重取消引用。代码检查表明获得了显着的 yield (设置与上述相同):

before = time.time()
sub_direct = my_list[0]
for i in range (iterations):
    if sub_direct[0] == 1 : break
after=time.time()

sub_direct_time = after - before
print("Sub-direct check time: "+str(sub_direct_time))

print("Multiple: "+str(sub_direct_time/direct_time))

输出:

Sub-direct check time: 8.609910488128662
Multiple: 1.2680250336804944

根据运行情况,似乎会产生大约一半的性能损失。

最佳答案

不可能。 Python 引用不是那样工作的。引用始终引用对象,而不是其他引用或对象片段。

如果您从不重新分配 list[0],那么您可以保存对该子列表的引用,因此您只需执行 sublist[0]:

sublist = list[0]
...
do_whatever_with(sublist[0])  # instead of list[0][0]

此外,不要将您的变量称为listlist 类型在该名称上有 dibs,当您想对某些内容调用 list 时,您会感到困惑。

关于python - 如何在 Python 中捕获对列表项的直接引用以提高速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57547402/

相关文章:

java - 如何将集合拆分为子集合?

编程语言|如何创建一个类模块来构建对象并将它们分配给数组/集合

javascript - 在 Node.js 中使用 Express 渲染数组中的每个对象

javascript - PHP 获取对象键

java - Python脚本参数化

python - 如何在 Ubuntu 上正确安装多个非软件包 Distribute/virtualenv/pip 生态系统?

python - 将 Pandas 数据框列导入为字符串而不是 int 或 float

元组列表时的 Python 3 : When to use dict,?

python - 为什么第一个值发生变化而第二个值没有变化?

.NET 的 Python : ImportError: No module named warnings