Python:从引用的位置替换列表,而不是创建新的 reference/list
Python: Replace a list in place from where it is referenced, not create a new reference/list
我在 Python 中处理相当多的值(内存占用为 5GB)。
有时,我需要按键访问值,有时我需要循环值。出于性能原因,我在启动时将 Dict 转换为 List,因此我可以:
- 在我想通过键访问值的情况下使用字典
- 在我想循环值的情况下使用列表
my_big_dict_of_values
my_big_values_list = list(my_big_dict_of_values.values())
为了清楚起见,这里有一个性能比较:
>some_dict = dict(zip(range(1000000), reversed(range(1000000))))
>some_list = list(some_dict.values())
>%timeit for t in some_dict.values(): t
21.1 ms ± 483 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
>%timeit for t in some_list: t
16.1 ms ± 1.31 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
当我需要根据用户输入从字典中删除键时,我的问题就出现了。
首先,我使用以下命令从字典中删除条目:
for key in keys_to_remove:
del(my_big_dict_of_values[key])
经过这次操作,我也想更新my_big_values_list
。我可以这样做:
解决方案 A(慢)
indexes_to_remove = list()
for idx, value in enumerate(my_big_values_list):
if value.key in keys_to_remove:
indexes_to_remove.append(idx)
for index in sorted(indexes_to_remove, reverse=True):
del my_big_values_list[index]
然而,这真的很慢而且很麻烦。
理想情况下,我想再次从字典创建列表:
解决方案 B(快速参考问题)
my_big_values_list = list(my_big_dict_of_values.values())
这很快,但似乎创建了一个新的引用。我需要替换传递给其他 classes/functions 的 my_big_values_list
的所有引用,这看起来很奇怪,例如举例说明。
my_big_dict_of_values
my_big_values_list = list(
my_big_dict_of_values.values())
handle_process = handle_process_class(
my_big_dict_of_values, my_big_values_list)
userinput = userinput(handle_process)
handle_process.calculate()
def userinput_class():
def __init__(handle_process):
self.handle_process = handle_process
def user_del_key(key):
del(self.handle_process.my_big_dict_of_values[key])
# Update list here too:
# Solution A works
# Solution B throws error in
# handle_process.calculate() because
# handle_process still has old list
def handle_process_class():
def __init__(my_big_dict_of_values, my_big_values_list):
self.my_big_dict_of_values = my_big_dict_of_values
self.my_big_values_list = my_big_values_list
def calculate(self):
return len(self.my_big_values_list)
有没有办法就地修改 my_big_values_list
,但只需替换为新列表(例如 list(my_big_dict_of_values.values()))。
我已经阅读了如何 Python 传递对值的引用,我想我理解了其中的大部分内容。这就是为什么我想出了解决方案A,但我不知道如何使用解决方案B来修改引用列表。也许有人可以解释这里发生了什么?
要就地修改列表,分配给它的切片:
my_big_values_list[:] = list(my_big_dict_of_values.values())
示例:
>>> my_big_dict_of_values = {"a": 1, "b": 2, "c": 3}
>>> my_big_values_list = list(my_big_dict_of_values.values())
>>> another_list_reference = my_big_values_list
>>> print(my_big_values_list, another_list_reference)
[1, 2, 3] [1, 2, 3]
>>> del(my_big_dict_of_values["b"])
>>> my_big_values_list[:] = list(my_big_dict_of_values.values())
>>> print(my_big_values_list, another_list_reference)
[1, 3] [1, 3]
但是在性能和内存使用方面,你应该考虑是否真的需要一个单独的巨大列表,因为你可以直接循环 dictionary.values()
。
我在 Python 中处理相当多的值(内存占用为 5GB)。
有时,我需要按键访问值,有时我需要循环值。出于性能原因,我在启动时将 Dict 转换为 List,因此我可以:
- 在我想通过键访问值的情况下使用字典
- 在我想循环值的情况下使用列表
my_big_dict_of_values
my_big_values_list = list(my_big_dict_of_values.values())
为了清楚起见,这里有一个性能比较:
>some_dict = dict(zip(range(1000000), reversed(range(1000000))))
>some_list = list(some_dict.values())
>%timeit for t in some_dict.values(): t
21.1 ms ± 483 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
>%timeit for t in some_list: t
16.1 ms ± 1.31 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
当我需要根据用户输入从字典中删除键时,我的问题就出现了。 首先,我使用以下命令从字典中删除条目:
for key in keys_to_remove:
del(my_big_dict_of_values[key])
经过这次操作,我也想更新my_big_values_list
。我可以这样做:
解决方案 A(慢)
indexes_to_remove = list()
for idx, value in enumerate(my_big_values_list):
if value.key in keys_to_remove:
indexes_to_remove.append(idx)
for index in sorted(indexes_to_remove, reverse=True):
del my_big_values_list[index]
然而,这真的很慢而且很麻烦。
理想情况下,我想再次从字典创建列表:
解决方案 B(快速参考问题)
my_big_values_list = list(my_big_dict_of_values.values())
这很快,但似乎创建了一个新的引用。我需要替换传递给其他 classes/functions 的 my_big_values_list
的所有引用,这看起来很奇怪,例如举例说明。
my_big_dict_of_values
my_big_values_list = list(
my_big_dict_of_values.values())
handle_process = handle_process_class(
my_big_dict_of_values, my_big_values_list)
userinput = userinput(handle_process)
handle_process.calculate()
def userinput_class():
def __init__(handle_process):
self.handle_process = handle_process
def user_del_key(key):
del(self.handle_process.my_big_dict_of_values[key])
# Update list here too:
# Solution A works
# Solution B throws error in
# handle_process.calculate() because
# handle_process still has old list
def handle_process_class():
def __init__(my_big_dict_of_values, my_big_values_list):
self.my_big_dict_of_values = my_big_dict_of_values
self.my_big_values_list = my_big_values_list
def calculate(self):
return len(self.my_big_values_list)
有没有办法就地修改 my_big_values_list
,但只需替换为新列表(例如 list(my_big_dict_of_values.values()))。
我已经阅读了如何 Python 传递对值的引用,我想我理解了其中的大部分内容。这就是为什么我想出了解决方案A,但我不知道如何使用解决方案B来修改引用列表。也许有人可以解释这里发生了什么?
要就地修改列表,分配给它的切片:
my_big_values_list[:] = list(my_big_dict_of_values.values())
示例:
>>> my_big_dict_of_values = {"a": 1, "b": 2, "c": 3}
>>> my_big_values_list = list(my_big_dict_of_values.values())
>>> another_list_reference = my_big_values_list
>>> print(my_big_values_list, another_list_reference)
[1, 2, 3] [1, 2, 3]
>>> del(my_big_dict_of_values["b"])
>>> my_big_values_list[:] = list(my_big_dict_of_values.values())
>>> print(my_big_values_list, another_list_reference)
[1, 3] [1, 3]
但是在性能和内存使用方面,你应该考虑是否真的需要一个单独的巨大列表,因为你可以直接循环 dictionary.values()
。