Python: заменить список в том месте, на которое он ссылается, а не создавать новую ссылку / список - PullRequest
0 голосов
/ 22 января 2019

Я работаю с довольно большим количеством значений в Python (объем памяти составляет 5 ГБ).

Иногда мне нужно получить доступ к значениям по ключу, иногда мне нужно зациклить значения.Из соображений производительности при запуске я конвертирую Dict в список, поэтому я могу:

  • использовать Dict в тех случаях, когда я хочу получить доступ к значениям по ключу
  • , использовать списокв случаях, когда я хочу зациклить значения
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)

Моя проблема возникает, когда мне нужноудалить ключи из dict на основе ввода пользователя.Сначала я удаляю записи из dict с помощью:

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]

Однако, это действительно медленно и громоздко.

В идеале, яхотел бы просто снова создать список из dict с помощью:

Решение B (Быстро с проблемой ссылки)

my_big_values_list = list(my_big_dict_of_values.values())

Это быстро, но, похоже,создать новую ссылку.Мне нужно будет заменить все ссылки 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 для изменения ссылочного списка.Возможно, кто-то может объяснить, что здесь происходит?

1 Ответ

0 голосов
/ 22 января 2019

Чтобы изменить список на месте, присвойте его срезу:

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().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...