Ответ 1
Перечисления списков предоставляют сжатый способ создания списков. Общие приложения - создавать новые списки, в которых каждый элемент является результатом некоторых операций, применяемых к каждому члену другой последовательности или итерабельной, или для создания подпоследовательности тех элементов, которые удовлетворяют определенному условию.
О вашем вопросе, понимание списка делает то же самое, что и следующий "простой" код Python:
>>> l = []
>>> for x in range(10):
... l.append(x**2)
>>> l
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Как вы пишете его в одной строке? Хм... мы можем... возможно... использовать map()
с lambda
:
>>> list(map(lambda x: x**2, range(10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Но разве не проще и проще просто использовать понимание списка?
>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
В принципе, мы можем сделать что-нибудь с x
. Не только x**2
. Например, запустите метод x
:
>>> [x.strip() for x in ('foo\n', 'bar\n', 'baz\n')]
['foo', 'bar', 'baz']
Или используйте x
как еще один аргумент функции:
>>> [int(x) for x in ('1', '2', '3')]
[1, 2, 3]
Мы также можем, например, использовать x
как ключ объекта dict
. Давайте посмотрим:
>>> d = {'foo': '10', 'bar': '20', 'baz': '30'}
>>> [d[x] for x in ['foo', 'baz']]
['10', '30']
Как насчет комбинации?
>>> d = {'foo': '10', 'bar': '20', 'baz': '30'}
>>> [int(d[x].rstrip('0')) for x in ['foo', 'baz']]
[1, 3]
И так далее.
Вы также можете использовать if
или if...else
в понимании списка. Например, вам нужны нечетные числа в range(10)
. Вы можете сделать:
>>> l = []
>>> for x in range(10):
... if x%2:
... l.append(x)
>>> l
[1, 3, 5, 7, 9]
А это слишком сложно. Как насчет следующей версии?
>>> [x for x in range(10) if x%2]
[1, 3, 5, 7, 9]
Чтобы использовать тернарное выражение if...else
, вам нужно поставить if ... else ...
после x
, не после range(10)
:
>>> [i if i%2 != 0 else None for i in range(10)]
[None, 1, None, 3, None, 5, None, 7, None, 9]
Вы слышали о вложенном понимании списка? Вы можете поместить два или более for
в одно понимание списка. Например:
>>> [i for x in [[1, 2, 3], [4, 5, 6]] for i in x]
[1, 2, 3, 4, 5, 6]
>>> [j for x in [[[1, 2], [3]], [[4, 5], [6]]] for i in x for j in i]
[1, 2, 3, 4, 5, 6]
Расскажите о первой части, for x in [[1, 2, 3], [4, 5, 6]]
, которая дает [1, 2, 3]
и [4, 5, 6]
. Затем for i in x
дает 1
, 2
, 3
и 4
, 5
, 6
.
Предупреждение: Вам всегда нужно поставить for x in [[1, 2, 3], [4, 5, 6]]
перед for i in x
:
>>> [j for j in x for x in [[1, 2, 3], [4, 5, 6]]]
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'x' is not defined
Мы также установили понимание, выражения выражений и выражения генератора.
установить оповещения, а перечислимые ошибки в основном одинаковы, но первый возвращает набор вместо списка:
>>> {x for x in [1, 1, 2, 3, 3, 1]}
{1, 2, 3}
Это то же самое, что:
>>> set([i for i in [1, 1, 2, 3, 3, 1]])
{1, 2, 3}
A определение dict выглядит как набор, но использует {key: value for key, value in ...}
или {i: i for i in ...}
вместо {i for i in ...}
.
Например:
>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
И он равен:
>>> d = {}
>>> for i in range(5):
... d[i] = i**2
>>> d
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Предоставляет ли (i for i in range(5))
кортеж? Нет!, это выражение генератора. Что возвращает генератор :
>>> (i for i in range(5))
<generator object <genexpr> at 0x7f52703fbca8>
Это то же самое, что:
>>> def gen():
... for i in range(5):
... yield i
>>> gen()
<generator object gen at 0x7f5270380db0>
И вы можете использовать его как генератор:
>>> gen = (i for i in range(5))
>>> next(gen)
0
>>> next(gen)
1
>>> list(gen)
[2, 3, 4]
>>> next(gen)
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration
Примечание. Если вы используете понимание списка внутри функции, вам не нужно []
, если эта функция может зацикливаться на генераторе. Например, sum()
:
>>> sum(i**2 for i in range(5))
30
Связанный (об генераторах): Понимание генераторов в Python.