Списки в Python: Len, Pop, Index и List Comprehension

Списки Python похожи на массивы в JavaScript. Это один из встроенных типов данных, использующийся для хранения наборов данных.

В этой статье:

Базовое использование

Как создать список

Пустой список создается при помощи пары квадратных скобок:

empty_list = []
print(type(empty_list)) # <class 'list'>
print(len(empty_list)) # 0

Можно создать список, сразу содержащий какие-то элементы. В этом случае они перечисляются через запятую и помещаются в квадратные скобки. Элементы в списках могут быть гетерогенными (т. е., разных типов), хотя обычно бывают гомогенными (одного типа):

homogeneous_list = [1, 1, 2, 3, 5, 8]
print(homogeneous_list) # [1, 1, 2, 3, 5, 8]
print(len(homogeneous_list)) # 6

heterogeneous_list = [1, "Hello, Pythonist!"]
print(heterogeneous_list) # [1, 'Hello, Pythonist!']
print(len(heterogeneous_list)) # 2

Для создания списков также может использоваться конструктор list:

empty_list = list()  # Создаем пустой список
print(empty_list)  # []
new_list = list("Hello, Pythonist!")  # Новый список создается путем перебора заданного итерируемого объекта.
print(new_list)  # ['H', 'e', 'l', 'l', 'o', ',', ' ', 'P', 'y', 't', 'h', 'o', 'n', 'i', 's', 't', '!']

Также при создании списков используется List Comprehension, к которому мы еще вернемся.

Обращение к элементам списка

Вывод всего списка:

my_list = [1, 2, 9, 16, 25]
print(my_list)  # [1, 2, 9, 16, 25]

Вывести отдельные элементы списка можно, обратившись к ним по индексу (не забываем, что отсчет начинается с нуля).

print(my_list[0])  # 1
print(my_list[1])  # 2
print(my_list[2])  # 9

В Python для обращения к элементам можно использовать и отрицательные индексы. При этом последний элемент в списке будет иметь индекс -1, предпоследний — -2 и так далее.

print(my_list[-1])  # 25
print(my_list[-2])  # 16
print(my_list[-3])  # 9

Распаковка списков (для python-3). Если поставить перед именем списка звездочку, все элементы этого списка будут переданы функции в качестве отдельных аргументов.

my_list = [1, 2, 9, 16, 25]
print(my_list)  # [1, 2, 9, 16, 25]
print(*my_list)  # 1 2 9 16 25

words = ["I", "love", "Python", "I", "love"]
print(words)  # ['I', 'love', 'Python', 'I', 'love']
print(*words)  # I love Python I love

Списки мутабельны

Списки — это изменяемые контейнеры. То есть, вы можете изменять содержимое списка, добавляя и удаляя элементы.

Элементы списка можно перегруппировать, используя для индексирования другой список.

Создадим новый список из элементов списка my_list, а индексы нужных элементов возьмем из списка my_index:

my_list = [1, 2, 9, 16, 25, 34, 53, 21]
my_index = [5, 2, 0]
my_new_list = [my_list[i] for i in my_index]
print(my_new_list)  # [34, 9, 1]

Методы списков

len()

Метод len() возвращает длину объекта (списка, строки, кортежа или словаря).

len() принимает один аргумент, который может быть или последовательностью (например, строка, байты, кортеж, список, диапазон), или коллекцией (например, словарь, множество, frozenset).

list1 = [123, 'abc', 'apple']  # список
print(len(list1)) # в списке 3 элемента, в выводе команды будет "3"

str1 = 'basketball'  # строка
print(len(str1))  # в строке 9 букв, в выводе команды будет "9"

tuple1 = (2, 3, 4, 5)  # кортеж
print(len(tuple1))  # в кортеже 4 элемента, в выводе команды будет "4"

dict1 = {'name': 'John', 'age': 4, 'score': 45} # словарь
print(len(dict1))  # в словаре 3 пары ключ-значение, в выводе команды будет "3"

index()

index() возвращает индекс элемента. Сам элемент передается методу в качестве аргумента. Возвращается индекс первого вхождения этого элемента (т. е., если в списке два одинаковых элемента, вернется индекс первого).

numbers = [1, 2, 2, 3, 9, 5, 6, 10]
words = ["I", "love", "Python", "I", "love"]

print(numbers.index(9)) # 4
print(numbers.index(2)) # 1
print(words.index("I")) # 0
print(words.index("JavaScript")) # возвращает ValueError, поскольку 'JavaScript' в списке 'words' нет

Первый результат очевиден. Второй и третий output демонстрируют возврат индекса именно первого вхождения.

Цифра «2» встречается в списке дважды, первое ее вхождение имеет индекс 1, второе — 2. Метод index() возвращает индекс 1.

Аналогично возвращается индекс 0 для элемента «I».

Если элемент, переданный в качестве аргумента, вообще не встречается в списке, вернется ValueError. Так получилось с попыткой выяснить индекс «JavaScript» в списке words.

Опциональные аргументы

Чтобы ограничить поиск элемента конкретной подпоследовательностью, можно использовать опциональные аргументы.

words = ["I", "am", "a", "I", "am", "Pythonista"]
print(words.index("am", 2, 5)) # 4

Метод index() будет искать элемент «am» в диапазоне от элемента с индексом 2 (включительно) до элемента с индексом 5 (этот последний элемент не входит в диапазон).

При этом возвращаемый индекс — индекс элемента в целом списке, а не в указанном диапазоне.

pop()

Метод pop() удаляет и возвращает последний элемент списка.

Этому методу можно передавать в качестве параметра индекс элемента, который вы хотите удалить (это опционально). Если конкретный индекс не указан, метод pop() удаляет и возвращает последний элемент списка.

Если в списке нет указанного вами индекса, метод выбросит exception IndexError: pop index out of range.

cities = ['New York', 'Dallas', 'San Antonio', 'Houston', 'San Francisco']

print "City popped is: ", cities.pop() # City popped is: San Francisco
print "City at index 2 is  : ", cities.pop(2) # City at index 2 is: San Antonio

Базовый функционал стека

Для реализации базового функционала стека в программах на Python часто используется связка метода pop() и метода append():

stack = []

for i in range(5):
    stack.append(i)

while len(stack):
    print(stack.pop())

List Comprehension

List Comprehension это создание списка путем итерации в цикле уже существующего списка (с соблюдением указанных условий). Поначалу такой подход может казаться сложным, но когда разберетесь, вы поймете, насколько это просто и быстро.

Чтобы разобраться в list comprehension, нужно для начала обратиться к обычной итерации списка. В следующем простом примере показано, как вернуть новый список, состоящий только из четных чисел старого.

# просто любой список чисел
some_list = [1, 2, 5, 7, 8, 10]

# пустой список, который будет заполняться четными числами из первого списка
even_list = []

for number in some_list:
  if number % 2 == 0:
    even_list.append(number)

print(even_list) # [2, 8, 10]

Давайте разберем этот пример. Сначала мы создаем список с числами. Затем создаем пустой список, в котором будут сохраняться результаты, полученные в цикле. Дальше идет сам цикл, в котором мы перебираем числа из первого списка и проверяем, являются ли они четными. Если число делится на 2 без остатка, мы добавляем его в список четных чисел. Для получения нужного результата нам потребуется 5 строк кода (без учета комментариев), да еще пробелы.

А теперь давайте посмотрим пример, в котором мы делаем все то же самое, но с помощью list comprehension.

# просто любой список чисел
some_list = [1, 2, 5, 7, 8, 10]

# List Comprehension
even_list = [number for number in some_list if number % 2 == 0]
print(even_list) # [2, 8, 10]

Давайте возьмем еще пример. Создадим список, каждый элемент которого будет элементом старого списка, умноженным на 7.

my_starting_list = [1, 2, 3, 4, 5, 6, 7, 8]
my_new_list = []

for item in my_starting_list:
    my_new_list.append(item * 7)
print(my_new_list)  # [7, 14, 21, 28, 35, 42, 49, 56]

С помощью list comprehension можно достичь того же результата:

my_starting_list = [1, 2, 3, 4, 5, 6, 7, 8]
my_new_list = [item * 7 for item in my_starting_list]

print(my_new_list)  # [7, 14, 21, 28, 35, 42, 49, 56]

Вообще list comprehension пишется в соответствии со следующей формулой:

my_list = [{operation with input n} for n in {python iterable}]

В блоке {operation with input n} вы указываете, что конкретно нужно сделать с элементом, который возвращает итерация объекта. В нашем примере это n * 7, но операция может быть любой, как очень простой, так и очень сложной.

В блок {python iterable} нужно вставить имя объекта, который вы будете перебирать в цикле. В нашем примере это был список, но мог быть кортеж или диапазон.

List comprehension добавляет элемент из существующего списка в новый, если соблюдается какое-то условие. Этот способ лаконичнее, а в большинстве случаев еще и намного быстрее. Иногда применение list comprehension может ухудшить читаемость кода, поэтому разработчику нужно действовать по ситуации.

Примеры использования list comprehension с условиями

Вносим в новый список только четные числа:

only_even_list = [i for i in range(13) if i%2==0]
print(only_even_list)  # [0, 2, 4, 6, 8, 10, 12]

Это эквивалентно следующему циклу:

only_even_list = list()
for i in range(13):
  if i%2 == 0:
    only_even_list.append(i)
print(only_even_list)  # [0, 2, 4, 6, 8, 10, 12]

List comprehension может также содержать вложенные if-условия. Обратите внимание на следующий пример:

divisible = list()
for i in range(50):
  if i % 2 == 0:
    if i % 3 == 0:
      divisible.append(i)
print(divisible)  # [0, 6, 12, 18, 24, 30, 36, 42, 48]

С применением list comprehension этот код можно переписать следующим образом:

divisible = [i for i in range(50) if i % 2 == 0 if i % 3 == 0]
print(divisible)  # [0, 6, 12, 18, 24, 30, 36, 42, 48]

С list comprehension также может использоваться if-else. В следующем примере мы берем диапазон чисел от 0 до 10 и добавляем в наш список все четные числа из этого диапазона, а нечетные добавляем после умножения на -1.

list_1 = [i if i % 2 == 0 else i * -1 for i in range(10)]
print(list_1)  # [0, -1, 2, -3, 4, -5, 6, -7, 8, -9]