Я видел, что на самом деле есть два (возможно, больше) способа объединения списков в Python: Один из способов - это использовать метод extend ():
a = [1, 2]
b = [2, 3]
b.extend(a)
другой использовать оператор плюс (+):
b += a
Теперь я задаюсь вопросом: какой из этих двух вариантов является «питоническим» способом объединения списков и есть ли разница между ними (я посмотрел официальный учебник по Python, но ничего не нашел по этой теме).
.__iadd__()
/.__add__()
/.__radd__()
против.extend()
Ответы:
Единственное отличие на уровне байт-кода заключается в том, что этот
.extend
способ включает вызов функции, который в Python немного дороже, чемINPLACE_ADD
.На самом деле вам не о чем беспокоиться, если вы не выполняете эту операцию миллиарды раз. Вполне вероятно, однако, что узкое место будет лежать в другом месте.
источник
.__iadd__()
/.__add__()
/.__radd__()
против.extend()
Вы не можете использовать + = для нелокальной переменной (переменная, которая не является локальной для функции, а также не глобальной)
Это потому, что для расширенного случая компилятор загрузит переменную,
l
используяLOAD_DEREF
инструкцию, но для + = он будет использоватьLOAD_FAST
- и вы получите*UnboundLocalError: local variable 'l' referenced before assignment*
источник
Вы можете связывать вызовы функций, но не можете + = вызов функции напрямую:
источник
Я бы сказал, что есть некоторая разница, когда речь идет о numpy (я только что увидел вопрос о объединении двух списков, а не массива numpy, но, поскольку это может быть проблемой для новичка, такого как я, я надеюсь, что это может кому-то помочь кто ищет решение этого поста), к примеру.
он вернется с ошибкой
ValueError: операнды не могут быть переданы вместе с формами (0,) (4,4,4)
b.extend(a)
работает отличноисточник
Из исходного кода CPython 3.5.2 : большой разницы нет.
источник
extend () работает с любыми повторяемыми *, + = работает с некоторыми, но может стать прикольным.
Python 3.6
* уверен, что .extend () работает с любой итерацией, но, пожалуйста, прокомментируйте, если я ошибаюсь
источник
list.extend(iterable) Extend the list by appending all the items from the iterable. Equivalent to a[len(a):] = iterable.
думаю, я ответил на свою звездочку.+=
оператор с объектами разных типов (в отличие от двух списков, как в вопросе), вы не можете ожидать, что вы получите объединение объектов. И вы не можете ожидать, что будетlist
возвращен тип. Посмотрите на ваш код, вы получитеnumpy.ndarray
вместоlist
.На самом деле, существует различие между тремя вариантами:
ADD
,INPLACE_ADD
иextend
. Первый всегда медленнее, а два других примерно одинаковы.С этой информацией я бы предпочел использовать
extend
, что быстрееADD
, и, как мне кажется, более явно о том, что вы делаете, чемINPLACE_ADD
.Попробуйте следующий код несколько раз (для Python 3):
источник
ADD
сINPLACE_ADD
иextend()
.ADD
создает новый список и копирует в него элементы двух оригинальных списков. Конечно, это будет медленнее, чем на месте операцииINPLACE_ADD
иextend()
.Эта информация находится в FAQ по программированию :
Вы также можете убедиться в этом в исходном коде CPython: https://github.com/python/cpython/blob/v3.8.2/Objects/listobject.c#L1000-L1011
источник
Согласно Python для анализа данных.
«Обратите внимание, что объединение списков путем сложения является сравнительно дорогой операцией, поскольку необходимо создать новый список и скопировать объекты. Использование расширения для добавления элементов в существующий список, особенно если вы создаете большой список, обычно предпочтительнее. Таким образом,
быстрее конкатенативной альтернативы:
источник
everything = everything + temp
не обязательно реализуется так же, какeverything += temp
.everything += temp
реализован таким образом, чтоeverything
его не нужно копировать. Это в значительной степени делает ваш ответ спорным.