Зірочка у виклику функції


111

Я використовую itertools.chain для "вирівнювання" списку таким чином:

uniqueCrossTabs = list(itertools.chain(*uniqueCrossTabs))

чим це відрізняється від того, щоб сказати:

uniqueCrossTabs = list(itertools.chain(uniqueCrossTabs))

8
Перегляньте розпакування списків аргументів у документах Python для отримання додаткової інформації.
Кай

8
Ви також повинні перевірити **оператора - він робить те саме, що і *з аргументами ключових слів.
Шон Віейра

Відповіді:


181

* є оператором "splat": він приймає список як вхідний і розширює його на фактичні позиційні аргументи у виклику функції.

Так що якщо uniqueCrossTabsбуло [ [ 1, 2 ], [ 3, 4 ] ], то itertools.chain(*uniqueCrossTabs)те саме, що говоритиitertools.chain([ 1, 2 ], [ 3, 4 ])

Це, очевидно, відрізняється від проходження просто uniqueCrossTabs. У вашому випадку у вас є список списків, які ви хочете вирівняти; що itertools.chain()полягає в тому, щоб повернути ітератор за конкатенацію всіх позиційних аргументів, які ви передаєте йому, де кожен позиційний аргумент є ітерабельним самостійно.

Іншими словами, ви хочете передати кожен список uniqueCrossTabsяк аргумент chain(), який з'єднає їх разом, але у вас немає списків в окремих змінних, тому ви використовуєте *оператор для розширення списку списків на кілька аргументів списку.

Як в коментарях зазначила Йочен Рітцель, chain.from_iterable()вона більше підходить для цієї операції, оскільки передбачає, що для початку слід здійснити єдиний ітерабел ітерабелів. Ваш код потім стає просто:

uniqueCrossTabs = list(itertools.chain.from_iterable(uniqueCrossTabs))

9
@larsmans: Я думаю, що цей термін є більш популярним у світі Ruby, але він здається прийнятним і для Python. Мені це подобається, тому що це цікаво сказати ;-)
Cameron

1
@larsmans: Цікаво! Я завжди думав, що це стосується дії розпакування списку в список аргументів, а не власне самого символу.
Камерон

1
Можливо, рядки - не найкращий приклад, тому що не всі бачать рядки як ітерабельні. Btw: Замість того chain(*it), щоб писати chain.from_iterable(it).
Jochen Ritzel

@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] None None
>>> foo(*[1, 2, 3])
1 2 3
>>> def bar(*a):
...   print a
... 
>>> bar([1, 2, 3])
([1, 2, 3],)
>>> bar(*[1, 2, 3])
(1, 2, 3)

послідовне пояснення з прикладами. +1!
AruniRC

28

Просто альтернативний спосіб пояснення поняття / його використання.

import random

def arbitrary():
    return [x for x in range(1, random.randint(3,10))]

a, b, *rest = arbitrary()

# a = 1
# b = 2
# rest = [3,4,5]

3
це важливо і не згадується в іншому місці
Гершом

1
Ця відповідь не стосується конкретного питання, але є важливим застосуванням зірочки (тому я вважаю, що підходить під досить "туманною" назвою). Одночасно з цим, ще одна важлива програма є у визначенні функцій: def func(a, b, *args):Докладнішу інформацію див. У цій відповіді .
ASL
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.