Разница между zip(список) и zip(* список)

Я пользуюсь списком p = [[1,2,3],[4,5,6]]

Если я сделаю:

>>>d=zip(p)
>>>list(d)
[([1, 2, 3],), ([4, 5, 6],)]

Хотя то, что я на самом деле хочу, получается с помощью этого:

>>>d=zip(*p)
>>>list(d)
[(1, 4), (2, 5), (3, 6)]

Я обнаружил, что добавление '*' перед именем списка дает мой требуемый вывод, но я не могу разглядеть разницу в их работе. Можете ли вы объяснить разницу?

6 ответов

zip хочет, чтобы куча аргументов была заархивирована, но у вас есть один аргумент (список, элементы которого также являются списками). * при вызове функции "распаковывает" список (или другой итерируемый), делая каждый из его элементов отдельным аргументом. Так что без *, ты делаешь zip( [[1,2,3],[4,5,6]] ), С *, ты делаешь zip([1,2,3], [4,5,6]),

* Оператор распаковывает аргументы в операторе вызова функции.

Учти это

def add(x, y):
   return x + y

если у вас есть список t = [1,2]Скажете add(t[0], t[1]) который излишне многословен, или вы можете "распаковать" t на отдельные аргументы, используя * оператор так add(*t),

Это то, что происходит в вашем примере. zip(p) это как бег zip([[1,2,3],[4,5,6]]), У Zip есть один аргумент, поэтому он просто возвращает его в виде кортежа.

zip(*p) это как бег zip([1,2,3], [4,5,6]), Это похоже на бег zip(p[0], p[1]) и вы получите ожидаемый результат.

* символ известен как оператор распаковки. когда он появляется за итерируемым объектом, он поочередно передает элементы внутри итерируемого вызывающей функции. В этом случае, так как zip функция принимает список итераций, чтобы вернуть их выровненные столбцы, zip(*p) передает все предметы внутри p в качестве аргументов zip функция:

Следовательно, в этом случае zip(*p) равно:

zip([1,2,3],[4,5,6])

Также обратите внимание, что начиная с Python-3.5 вы можете распаковывать операторы в некоторых других случаях, кроме как в функциях. Одна из них называется распаковка на месте, что позволяет использовать распаковку внутри другой итерации.

In [4]: a = [1, 2, 3]

In [5]: b = [8, 9, *a, 0, 0]

In [6]: b
Out[6]: [8, 9, 1, 2, 3, 0, 0]

В двух словах, с x = [1,2,3]при звонке f(x)х получает 1 аргумент [1, 2, 3], Когда вы используете звездный оператор f(*x), f получает три аргумента, это эквивалентно вызову f(1,2,3),

Вот почему в документации Python вы часто будете видеть some_function(*args, **kwargs), Здесь оператор двойной звезды делает то же самое, но для словаря: с d={"some_arg":2, "some_other_arg":3}звонит f(**d) такой же как f(some_arg=2, some_other_arg=3),

Теперь, когда вы используете zip, фактически вы хотите сжать [1,2,3] с помощью [4,5,6], поэтому вы хотите передать 2 аргумента в zip, поэтому вам нужен оператор звезды. Без этого вы передаете только один аргумент.

Хотя это не ответ на вопрос, который вы задали, это должно помочь. Поскольку zip используется для объединения двух списков, вы должны сделать что-то вроде этого list(zip(p[0], p[1])) чтобы выполнить то, что вы ожидаете.

Оператор "*" распаковывает список и применяет его к функции. Функция zip берет n списков и создает пары n-кортежей из каждого элемента из обоих списков:

почтовый индекс ([повторяемый, ...])

Эта функция возвращает список кортежей, где i-й кортеж содержит i-й элемент из каждой последовательности аргументов или итераций. Возвращаемый список усекается по длине до длины самой короткой последовательности аргументов. Когда есть несколько аргументов одинаковой длины, zip() аналогичен map() с начальным аргументом None. С одним аргументом последовательности он возвращает список из 1 кортежа. Без аргументов возвращает пустой список.

В основном, используя * с [[1,2,3],[4,5,6]]Вы проходите [1,2,3] а также [4,5,6] в качестве аргументов для zip.

Другие вопросы по тегам