вам также следует проверить **оператор - он делает то же самое, что и *с аргументами ключевого слова.
Шон Виейра,
Ответы:
182
* является оператором «splat»: он принимает список в качестве входных данных и расширяет его до фактических позиционных аргументов при вызове функции.
Так что если uniqueCrossTabsбыло [ [ 1, 2 ], [ 3, 4 ] ], то itertools.chain(*uniqueCrossTabs)это то же самое, что сказатьitertools.chain([ 1, 2 ], [ 3, 4 ])
Это явно отличается от передачи просто uniqueCrossTabs. В вашем случае у вас есть список списков, которые вы хотите сгладить; что itertools.chain()возвращает итератор по объединению всех позиционных аргументов, которые вы ему передали, где каждый позиционный аргумент является итеративным сам по себе.
Другими словами, вы хотите передать каждый список в uniqueCrossTabsкачестве аргумента chain(), который объединит их в цепочку, но у вас нет списков в отдельных переменных, поэтому вы используете* оператор, чтобы развернуть список списков на несколько аргументов списка.
Как отметил в комментариях Йохен Ритцель, chain.from_iterable()он лучше подходит для этой операции, так как для начала предполагает наличие единственной итерации из итераций. Тогда ваш код станет просто:
@larsmans: Я думаю, что этот термин более популярен в мире Ruby, но он кажется приемлемым и для Python. Мне он нравится, потому что это забавно говорить ;-)
Кэмерон
1
@larsmans: Интересно! Я всегда думал, что это относится к действию распаковки списка в список аргументов, а не к самому персонажу.
Кэмерон
1
Возможно, строки - не лучший пример, потому что не все считают строки итерируемыми. Кстати: Вместо того, chain(*it)чтобы писать chain.from_iterable(it).
Йохен Ритцель 09
@Jochen: Вы абсолютно правы, я заменю его на числа. Кроме того, я даже не знал о from_iterableсуществовании! Я добавлю это в свой ответ в ближайшее время
Кэмерон
1
@Ramy: *только для разбиения списка на позиционные аргументы функции (так что да, очень специфично). Вы можете их for l in uniqueCrossTabs:перебрать. К сожалению, это трудно увидеть *в работе, так как это работает только тогда, когда вы передаете список в функцию (вместо передачи списка в качестве первого параметра *каждый элемент в списке передается как отдельный параметр, один за другим , как если бы они были набраны через запятую в списке параметров)
Кэмерон
72
Он разбивает последовательность на отдельные аргументы для вызова функции.
>>>def foo(a, b=None, c=None):...print a, b, c
...>>> foo([1,2,3])[1,2,3]NoneNone>>> foo(*[1,2,3])123>>>def bar(*a):...print a
...>>> bar([1,2,3])([1,2,3],)>>> bar(*[1,2,3])(1,2,3)
Этот ответ не относится к вопросу конкретно, но является важным применением звездочки (поэтому я думаю, что это уместно под довольно «туманным» заголовком). В том же духе еще одно важное приложение - определения функций: def func(a, b, *args):см. Этот ответ для получения дополнительной информации.
**
оператор - он делает то же самое, что и*
с аргументами ключевого слова.Ответы:
*
является оператором «splat»: он принимает список в качестве входных данных и расширяет его до фактических позиционных аргументов при вызове функции.Так что если
uniqueCrossTabs
было[ [ 1, 2 ], [ 3, 4 ] ]
, тоitertools.chain(*uniqueCrossTabs)
это то же самое, что сказатьitertools.chain([ 1, 2 ], [ 3, 4 ])
Это явно отличается от передачи просто
uniqueCrossTabs
. В вашем случае у вас есть список списков, которые вы хотите сгладить; чтоitertools.chain()
возвращает итератор по объединению всех позиционных аргументов, которые вы ему передали, где каждый позиционный аргумент является итеративным сам по себе.Другими словами, вы хотите передать каждый список в
uniqueCrossTabs
качестве аргументаchain()
, который объединит их в цепочку, но у вас нет списков в отдельных переменных, поэтому вы используете*
оператор, чтобы развернуть список списков на несколько аргументов списка.Как отметил в комментариях Йохен Ритцель,
chain.from_iterable()
он лучше подходит для этой операции, так как для начала предполагает наличие единственной итерации из итераций. Тогда ваш код станет просто:источник
chain(*it)
чтобы писатьchain.from_iterable(it)
.from_iterable
существовании! Я добавлю это в свой ответ в ближайшее время*
только для разбиения списка на позиционные аргументы функции (так что да, очень специфично). Вы можете ихfor l in uniqueCrossTabs:
перебрать. К сожалению, это трудно увидеть*
в работе, так как это работает только тогда, когда вы передаете список в функцию (вместо передачи списка в качестве первого параметра*
каждый элемент в списке передается как отдельный параметр, один за другим , как если бы они были набраны через запятую в списке параметров)Он разбивает последовательность на отдельные аргументы для вызова функции.
источник
Просто альтернативный способ объяснения концепции / ее использования.
источник
def func(a, b, *args):
см. Этот ответ для получения дополнительной информации.