Добавление списков по ссылке

yasakasa спросил: 13 июня 2018 в 11:47 в: python

Можно ли добавить два списка, используя ссылку для каждого списка вместо копии?

Например -

first_list = [1,2,3]
second_list = [5,6]
new_list = first_list + second_list
print(new_list)    # Will print [1,2,3,5,6]
first_list.append(4)
print(new_list)    # Should print [1,2,3,4,5,6]

Есть ли способ сделать это в Python? Или код переписывает мой единственный вариант?

Изменить: я удалил путаные комментарии, которые я сделал об использовании C ++ для этого.

1 ответ

Есть решение
abarnert ответил: 13 июня 2018 в 12:10

Вы не можете напрямую сделать это в Python больше, чем вы можете в C ++.

Но вы можете косвенно сделать это в Python точно так же, как вы можете в C ++: путем записи объекта, который выполняется на оба списка и отправления соответственно.

Например:

class TwoLists(collections.abc.Sequence):
    def __init__(self, a, b):
        self.a, self.b = a, b
    def __len__(self):
        return len(self.a) + len(self.b)
    def __getitem__(self, idx):
        # cheating a bit, not handling slices or negative indexing
        if idx < len(self.a):
            return self.a[idx]
        else:
            return self.b[idx - len(self.a)]

Теперь:

>>> first_list = [1,2,3]
>>> second_list = [5,6]
>>> two_lists = TwoLists(first_list, second_list)
>>> print(*two_lists)
1 2 3 5 6
>>> first_list.append(4)
>>> print(*two_lists)
1 2 3 4 5 6

Я думаю, что вы здесь отсутствовали, это фундаментальное различие между Python и C ++ в том, как работают переменные. Вкратце, каждая переменная Python (а также позиция атрибута и списка и т. Д.) В терминологии C ++ является ссылочной переменной.

Менее ошибочно:

Переменные C ++ (и атрибуты и т. Д.). ) являются местами памяти - они находятся там, где значения. Если вы хотите, чтобы a был ссылкой на значение в b, вам нужно сделать значение reference-to-b и сохранить его в a. (C ++ имеет немного магии, которая позволяет определять ссылочную переменную типа int& a = b, но вы не можете переназначить a для ссылки на c; если вы этого хотите, вам нужно явно использовать указатели, C-стиль.)

Переменные Python (и т. д.) являются именами значений, а значения живут там, где они хотят. Если вы хотите, чтобы a был ссылкой на значение в a, вы просто привязываете a к тому же значению b привязан к : a = b. (И, в отличие от C ++, вы можете переназначить a = c в любое время.)

Конечно, стоимость - это производительность: есть дополнительное косвенное отношение для достижения любого значения из его имени в Python, тогда как в C ++, это происходит только при использовании переменных указателя. Но эта стоимость почти всегда невидима по сравнению с другими накладными расходами Python (интерпретация байт-кода и динамически выглядящих имен в словарях и т. Д.), Поэтому для языка высокого уровня имеет смысл просто не дать вам выбор.


Все, что сказано, обычно нет веских оснований для этого в языке . Как Python, так и стандартная библиотека C ++ разработаны вокруг (аналогичных, но разных понятий) итераций.

В Python вам обычно не нужна последовательность, просто повторяемая. А цепочка двух итераций вместе тривиальна:

>>> from itertools import chain
>>> first_list = [1,2,3]
>>> second_list = [5,6]
>>> print(*chain(first_list, second_list))
1 2 3 5 6
>>> first_list.append(4)
>>> print(*chain(first_list, second_list))
1 2 3 4 5 6

Да, я могу только перебирать код chain один раз, но обычно это все, что вам нужно. (Как и в C ++, вам обычно требуется только цикл из begin(c) в end(c), а не для создания нового постоянного объекта, который хранится на них.)

И если вы думаете, что это обман, потому что я использую itertools, мы можем сами определить его:

def chain(*its):
    for it in its:
        yield from it
yasakasa ответил: 13 июня 2018 в 12:02
Спасибо. Это именно то, что мне нужно.