Разница между zip (list) и zip (* list)
Я использую список 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)]
Я обнаружил, что добавление "*" перед именем списка дает мой требуемый результат, но я не могу понять разницу в их работе. Не могли бы вы объяснить разницу?
Ответы
Ответ 1
zip
хочет, чтобы куча аргументов включалась вместе, но у вас есть один аргумент (список, элементы которого также являются списками). *
в вызове функции "распаковывает" список (или другой итерабельный), делая каждый из его элементов отдельным аргументом. Итак, без *
вы делаете zip( [[1,2,3],[4,5,6]] )
. С помощью *
вы делаете zip([1,2,3], [4,5,6])
.
Ответ 2
Оператор *
распаковывает аргументы в операторе вызова функции.
Рассмотрим это
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])
, и вы получите ожидаемый результат.
Ответ 3
Хотя это не тот ответ, который вы задали, он должен помочь. Поскольку zip используется для объединения двух списков, вы должны сделать что-то вроде этого list(zip(p[0], p[1]))
, чтобы выполнить то, что вы ожидаете.
Ответ 4
На самом деле *
является оператором распаковки, а поскольку функция zip
принимает список итераций, вы можете передать несколько итераций этой функции:
Итак, результатом *p
является:
[1,2,3],[4,5,6]
и zip(*p)
равно zip([1,2,3],[4,5,6])
.
Также для лучшего понимания обратите внимание, что *
можно использовать для распаковки списка:
>>> zip(*zip(*p))
[(1, 2, 3), (4, 5, 6)]
Вышеприведенная команда распаковывает результат zip(*p)
, чтобы у вас было:
zip((1, 4), (2, 5), (3, 6))
zip ([итерируемый,...])
Эта функция возвращает список кортежей, где i-й кортеж содержит i-й элемент из каждой из последовательностей аргументов или итераций. Возвращаемый список усекается по длине с длиной кратчайшей последовательности аргументов. Когда есть несколько аргументов, которые имеют одинаковую длину, zip() похож на map() с начальным аргументом None. С одним аргументом последовательности он возвращает список из 1-кортежей. Без аргументов он возвращает пустой список.
Ответ 5
В двух словах, при x = [1,2,3]
, при вызове f(x)
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, вы действительно хотите zip [1,2,3] с [4,5,6], поэтому вы хотите передать 2 аргумента в zip, поэтому вам нужен оператор-звезда. Без этого вы передаете только один аргумент.
Ответ 6
Оператор "*" распаковывает список и применяет его к функции. Функция zip принимает n списков и создает пары n-кортежей из каждого элемента из обоих списков:
zip ([итерируемый,...])
Эта функция возвращает список кортежей, где i-й кортеж содержит i-й элемент из каждой из последовательностей аргументов или итераций. возвращенный список усечен по длине до самой короткой последовательность аргументов. Когда есть несколько аргументов, которые являются такая же длина, zip() аналогична map() с начальным аргументом Никто. С одним аргументом последовательности он возвращает список из 1-кортежей. Без аргументов он возвращает пустой список.
В основном, используя *
с [[1,2,3],[4,5,6]]
, вы передаете [1,2,3]
и [4,5,6]
в качестве аргументов для zip.