Списки в Python


Синтаксис

Списки определяются в квадратных скобках []. Всё, что в квадратных скобках, называется индексами.

Извлечение индекса из списка

spam = ['кошка', 'собака', 'мышка']

Вывод:
spam[0]
'кошка'

spam[2]
'мышка'

Списки внутри списка

В списке могут находиться другие списки. Каждый внутренний список становится индексом.

spam = [['кошка', 'собака'], [10, 20, 30, 40, 50]]

spam[0]
['кошка', 'собака']

Отрицательные индексы

spam = ['кошка', 'собака', 'мышка']

spam[-1]
['мышка']

spam[-3]
['кошка']

spam[-2] + ' против ' + spam[-3]
'Кошка против мышка'


Индексы и срезы (slices)

Если два индекса разделены двоеточием, то это срез.

# это простой список с индексом
spam[1]

# а это список со срезом
spam[1:3]


В срезе первое значение — это индекс, с которого начинается срез. Второе значение — это индекс, на котором заканчивается срез.


spam = ['кошка', 'собака', 'мышка'] 

spam[0:3]
['кошка', 'собака', 'мышка']

spam[1:3]
['собака', 'мышка']

spam[0:-1]
['кошка', 'собака']


Можно пропустить один или оба индекса между срезом.


spam = ['кошка', 'собака', 'мышка'] 

spam[:2]
['кошка', 'собака']

spam[1:]
['собака', 'мышка']

spam[:]
 ['кошка', 'собака', 'мышка']

Изменение индексов в списке

spam = ['кошка', 'собака', 'мышка'] 

spam[0] = 'кот'
spam
['кот', 'собака', 'мышка']

spam[1] = spam[0]
spam
['кот', 'кот', 'мышка']

spam[-1] = 12345
spam
['кот', 'кот', '12345']

Конкатенация и репликация списков

Несколько списков можно объединять в один с помощью оператора присваивания +.

[1, 2, 3] + ['A', 'B', 'C']
[1, 2, 3, 'A', 'B', 'C']


Можно реплицировать список с помощью оператора умножения *.

['X', 'Y', 'Z'] * 3
['X', 'Y', 'Z', 'X', 'Y', 'Z', 'X', 'Y', 'Z']


Другие варианты.

spam = [1, 2, 3]
spam = spam + ['A', 'B', 'C']

spam
[1, 2, 3, 'A', 'B', 'C']

Удаление индекса из списка

Удалить определенный индекс можно с помощью оператора del.

spam = ['кошка', 'собака', 'мышка'] 

del spam[2]
spam
['кошка', 'собака']

del spam[1]
spam
['кошка']


Оператор del также может использоваться для удаления простой переменной. Но если вы попытаетесь использовать переменную после ее удаления, вы получите ошибку NameError, поскольку переменная больше не существует.

На практике почти никогда не нужно удалять простые переменные. Оператор del в основном используется для удаления индексов из списка.

supplies = ['Карандаши', 'Степлеры', 'Скрепки', 'Ластики', 'Кнопки']
for i in range(len(supplies)):
    print('В индексе ' + str(i) + ' в supplies содержатся ' + supplies[i])


Результат:

В индексе 0 в supplies содержатся Карандаши
В индексе 1 в supplies содержатся Степлеры
В индексе 2 в supplies содержатся Скрепки
В индексе 3 в supplies содержатся Ластики
В индексе 4 в supplies содержатся Кнопки


Использование range(len(supplies)) в цикле for удобно, потому что код в цикле может получить доступ к индексу (как переменная i) и значению этого индекса (как supplies[i]). range(len(supplies)) будет перебирать все индексы supplies, независимо от того, сколько элементов в них содержится.

Операторы in и not in

С помощью in и not in вы можете определить, находится ли значение в списке или нет.

Как и другие операторы, выражения in и not in используются в выражениях и соединяют два значения: значение, которое нужно искать в списке, и список, в котором его можно найти. Эти выражения приведут к логическому значению.

'собака' in ['кошка', 'собака', 'мышка']
True

spam = ['кошка', 'собака', 'мышка']
'кот'
False

'собака' not in spam
False

'кот' not in spam
True


Есть ли в списке этот питомец?


Следующая программа позволяет пользователю вводить имя питомца, а затем проверяет, есть ли имя в списке питомцев.

myPets = ['Васян', 'Тиша', 'Мурзик', 'Бобик']
print('Введите имя питомца: ')
name = input()
if name not in myPets:
    print('В списке нет питомца ' + name)
else:
    print(name + ' есть в списке.')


Результаты:

Введите имя питомца: 
Васян
Васян есть в списке. 

Введите имя питомца: 
Барбос
В списке нет питомца Барбос

Множественное присваивание

Множественное присваивание — это ярлык, который позволяет назначать несколько переменных со значениями в списке в одной строке кода. 

Поэтому вместо того, чтобы делать так:

cat = ['толстый', 'черный', 'наглый']
size = cat[0]
color = cat[1]
disposition = cat[2]


Можно сделать так:

cat = ['толстый', 'черный', 'наглый']
size, color, disposition = cat

Расширенные операторы присваивания

При присваивании значения переменной вы часто будете использовать саму переменную. Например, после присвоения 42 переменной spam, вы можете увеличить значение в spam на 1 с помощью следующего кода:

spam = 42
spam = spam + 1
spam
43


В качестве ярлыка вы можете использовать оператор расширенного присваивания +=, чтобы сделать то же самое:

spam = 42
spam += 1
spam
43


Таблица расширенных операторов присваивания

Расширенный операторЭвивалент этого оператора
 spam += 1 spam = spam + 1
 spam -= 1 spam = spam - 1
 spam *= 1 spam = spam * 1
 spam /= 1 spam = spam / 1
 spam %= 1 spam = spam % 1


+= также может выполнять конкатенацию строк и списков, а *= может выполнять репликацию строк и списков.

spam = 'Hello'
spam += ' world!'
spam
'Hello world!'


pet = ['Мурзик']
pet *= 3
pet
['Мурзик', 'Мурзик', 'Мурзик']

Методы и функции списков

Метод — это то же самое, что и функция, за исключением того, что он «вызывается» для значения.

Например, если значение списка было сохранено в spam, вы бы вызвали метод списка 
index() (который я объясню далее) в этом списке следующим образом: spam.index('hello'). Часть метода идет после значения, разделенного точкой.

Каждый тип данных имеет свой собственный набор методов. Например, тип data имеет несколько полезных методов для поиска, добавления, удаления и других манипуляций со значениями в списке.

Поиск значения в списке с помощью метода index ()

У значений списка есть метод index(), которому можно передать значение, и, если это значение существует в списке, возвращается индекс значения. Если значение отсутствует в списке, то Python выдаст ошибку ValueError.

spam = ['hello', 'hi', 'howdy', 'heyas']
spam.index('hello')
0

spam.index('heyas')
3

spam.index('howdy howdy howdy')
Traceback (most recent call last):
  File "<pyshell#31>", line 1, in 
    spam.index('howdy howdy howdy')
ValueError: 'howdy howdy howdy' is not in list


При наличии дубликатов значения в списке возвращается индекс его первого появления. Обратите внимание, что index() возвращает 1, а не 3.


spam = ['Один', 'Два', 'Три', 'Один']
spam.index('Один')
1

Добавление значений с помощью методов append() и insert()

Чтобы добавить новые значения в список, используйте методы append() и insert().

spam = ['кошка', 'собака', 'мышка']
spam.append('попугай')
spam
['кошка', 'собака', 'мышка', 'попугай']


Метод append() добавляет аргумент в конец списка. Метод insert() может вставить значение по любому индексу в списке.

Первый аргумент для 
insert() — это индекс для нового значения, а второй аргумент — это новое значение, которое нужно вставить.

spam = ['кошка', 'собака', 'мышка']
spam.insert(1, 'попугай')
spam
['кошка', 'попугай', 'собака', 'мышка' ]

Удаление значений из списка с помощью метода remove ()

Метод remove() передает значение, которое будет удалено из списка, к которому он обращен.

spam = ['кошка', 'собака', 'мышка']
spam.remove('мышка')
spam
['кошка', 'собака']


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

Оператор del хорошо использовать, когда вы знаете индекс значения, которое хотите удалить из списка. Метод remove() хорош, когда вы знаете значение, которое хотите удалить из списка.

Сортировка с помощью метода sort()

Списки числовых значений или списки строк могут быть отсортированы с помощью метода sort().

spam = [2, 5, 3.14, 1, -7]
spam.sort()
spam
[-7, 1, 2, 3.14, 5]

spam = ['кошка', 'собака', 'мышка', 'попугай']
spam.sort()

spam
['кошка', 'мышка', 'попугай', 'собака']


Можно передать True для обратного ключевого аргумента, чтобы sort () сортировал значения в обратном порядке.

spam = ['кошка', 'собака', 'мышка', 'попугай']
spam.sort(reverse=True)
spam
['собака', 'попугай', 'мышка', 'кошка']


Есть три вещи, которые вы должны знать о методе sort(). 

Во-первых, метод sort() сортирует список по месту; поэтому не пытайтесь получить возвращаемое значение, написав такой код, как spam = spam.sort().

Во-вторых, вы не можете сортировать списки, в которых есть как числовые, так и строковые значения, поскольку Python не знает, как сравнивать эти значения.


spam = [1, 3, 2, 4, 'кошка', 'мышка']
 spam.sort()
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in 
    spam.sort()
TypeError: unorderable types: str() < int()


В-третьих, sort() использует «ASCII порядок», а не фактический алфавитный порядок для сортировки строк. Это означает, что заглавные буквы идут перед строчными. Поэтому строчная буква a сортируется так, чтобы она шла после заглавной буквы Z.

spam = ['Васян', 'Тиша', 'Мурзик', 'кошка', 'собака', 'мышка']
spam.sort()
spam
['Васян', 'Мурзик', 'Тиша', 'кошка', 'мышка', 'собака']


Если вам нужно отсортировать значения в обычном алфавитном порядке, передайте str.lower для ключевого аргумента в вызове метода sort().

spam = ['a', 'z', 'A', 'Z']
spam.sort(key=str.lower)
spam
['a', 'A', 'z', 'Z']


Это заставляет функцию sort() обрабатывать все элементы в списке, как если бы они были строчными, без фактического изменения значений в списке.

Строки и кортежи




Списки не являются единственными типами данных, которые представляют упорядоченные последовательности значений.

Например, строки и списки на самом деле похожи, если считать строку «list» однотекстовых символов. Многое из того, что вы можете сделать со списками, также может быть сделано со строками: индексы; срезы; и используя их с 
for, с len() и с операторами in и not in.

name = 'Бобик'
name[0]
'Б'

name[-2]
'и'

 name[0:]
'Бобик'

'Бо' in name
True

'б' in name
False

'и' not in name
False

for i in name:
   print('* * * ' + i + ' * * *')

* * * Б * * *
* * * о * * *
* * * б * * *
* * * и * * *
* * * к * * *

Изменяемые и неизменяемые типы

Списки и строки важны по-разному. Значение списка является изменяемым типом данных: оно может иметь значения, добавленные, удаленные или измененные. Однако строка является неизменной: ее нельзя изменить. Попытка переназначить один символ в строке приводит к ошибке TypeError.

Правильный способ сделать строку изменяемой — это использовать срез и конкатенацию для построения новой строки путем копирования из частей старой строки.

name = 'Кошку звать Муся'
newName = name[0:5] + ' зовут ' + name[12:16]

name
Кошку звать Муся

newName
Кошку зовут Муся


Мы использовали [0:5] и [12:16] для обозначения символов, которые мы не хотим заменять. Обратите внимание, что исходная строка «Кошку звать Муся» не изменяется, потому что строки являются неизменяемыми.

Хотя значение списка является изменяемым, вторая строка в следующем коде не изменяет список в 
eggs.

eggs = [1, 2, 3]
eggs = [4, 5, 6]

eggs
[4, 5, 6]


Значение списка в eggs здесь не изменяется; новое и другое значение списка ([4, 5, 6]) перезаписывает старое значение списка ([1, 2, 3]). Если вы хотите изменить исходный список в eggs, чтобы он содержал [4, 5, 6], вам нужно будет сделать что-то вроде этого:

eggs = [1, 2, 3]


del eggs[2]
del eggs[1]
del eggs[0]

eggs.append(4)
eggs.append(5)
eggs.append(6)


eggs
[4, 5, 6]

Тип данных Tuple (Кортеж)

Тип данных кортеж практически идентичен типу данных списки, за исключением двух способов. Во-первых, кортежи печатаются с круглыми скобками (и) вместо квадратных скобок [и].

eggs = ('hello', 42, 0.5)

eggs[0]
'hello'

eggs[1:3]
(42, 0.5)

len(eggs)
3


Но основной способ отличия кортежей от списков заключается в том, что кортежи, как и строки, являются неизменяемыми. Кортежам нельзя изменять, добавлять или удалять их значения. Если вы попробуете изменить индекс в кортеже, то получите TypeError.

eggs = ('hello', 42, 0.5)
eggs[1] = 99
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in 
    eggs[1] = 99
TypeError: 'tuple' object does not support item assignment


Если в кортеже есть только одно значение, можно указать это, поместив запятую после значения в скобках. В противном случае Python будет думать, что вы только что ввели значение в обычных скобках. Запятая — это то, что дает Python знать, что это значение кортежа.

type(('hello',))
<class 'tuple'>

type(('hello'))
<class 'str'>


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

Преобразование типов с помощью функций list() и tuple()

Так же, как str(42) вернет '42', строковое представление целого числа 42, функции list() и tuple() вернут версии списка и кортежа значений, переданных им.

tuple(['кошка', 'собака', 5])
('кошка', 'собака', 5)

list(('кошка', 'собака', 5))
['кошка', 'собака', 5]

list('hello')
['h', 'e', 'l', 'l', 'o']

Ссылки

Как известно, переменные хранят строки и целые значения.

spam = 42
cheese = spam
spam = 100

spam
100

cheese
42


Вы присваиваете 42 переменной spam, а затем копируете значение в spam и присваиваете его переменной cheese. Когда вы позже измените значение в spam на 100, это не повлияет на значение в cheese. Это потому, что spam и cheese — это разные переменные, в которых хранятся разные значения.

Но списки не работают таким образом. Когда вы назначаете список переменной, вы фактически назначаете ссылку на список переменной. Ссылка — это значение, которое указывает на некоторый бит данных, а ссылка на список — это значение, которое указывает на список. Вот код, который облегчит понимание этого различия.

# 1
spam = [0, 1, 2, 3, 4, 5]
# 2
cheese = spam
# 3
cheese[1] = 'Hello!'

spam
[0, 'Hello!', 2, 3, 4, 5]

cheese
[0, 'Hello!', 2, 3, 4, 5]


1. Когда вы создаете список, вы присваиваете ему ссылку в переменной spam.

2. Но следующая строка копирует список spam только ссылку на cheese, а не само значение списка. Это означает, что значения, хранящиеся в spam и cheese, теперь относятся к одному и тому же списку. Существует только один базовый список, потому что сам список фактически никогда не копировался.

3. Поэтому, когда вы изменяете первый элемент cheese, вы изменяете тот же список, на который ссылается spam.

Переменные будут содержать ссылки на значения списка, а не сами значения списка. Но для строк и целых значений переменные просто содержат строковое или целое значение. Python использует ссылки всякий раз, когда переменные должны хранить значения изменяемых типов данных, таких как списки или словари. Для значений неизменяемых типов данных, таких как строки, целые числа или кортежи, переменные Python будут хранить само значение.

Хотя переменные Python технически содержат ссылки на значения списка или словаря, люди часто говорят, что переменная содержит список или словарь.

Передача ссылок

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

def eggs(someParameter):
    someParameter.append('Hello')
    
spam = [1, 2, 3]
eggs(spam)
print(spam)


Обратите внимание, что при вызове eggs () возвращаемое значение не используется для присвоения нового значения в spam. Вместо этого он изменяет список на месте, напрямую. При запуске эта программа выдает следующий вывод:


[1, 2, 3, 'Hello'] 

Хотя spam и someParameter содержат отдельные ссылки, они оба ссылаются на один и тот же список. Вот почему вызов метода append ('Hello') внутри функции влияет на список даже после возврата вызова функции. Помните это поведение: забыв, что Python обрабатывает переменные списка и словаря таким образом, может привести к путанице.

Модули copy() и deepcopy()

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


import copy spam = ['A', 'B', 'C', 'D']
cheese = copy.copy(spam) 
cheese[1] = 42 
spam ['A', 'B', 'C', 'D'] 
cheese ['A', 42, 'C', 'D']

Теперь переменные spam и cheese ссылаются на отдельные списки, поэтому при назначении 42 для индекса 7 изменяется только список в cheese. Как видно на рисунке, ссылки на ID больше не совпадают обоими переменными, потому что переменные ссылаются на независимые списки.  Если список, который необходимо скопировать, содержит списки, используйте функцию copy.deepcopy() вместо copy.copy(). Функция deepcopy() также скопирует эти внутренние списки.




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


Кортежи и строки, хотя в некоторых отношениях похожи на списки, являются неизменяемыми и не могут быть изменены. Переменная, которая содержит кортеж или строковое значение, может быть перезаписана новым кортежем или строковым значением, но это не то же самое, что модификация существующего значения на месте — как это делают, например, методы append() или remove(). Переменные не хранят значения списка напрямую; они хранят ссылки на списки. 


Это важное различие при копировании переменных или передачи списков в качестве аргументов в вызовах функций. Поскольку копируемое значение является ссылкой на список, имейте в виду, что любые изменения, внесенные в список, могут повлиять на другую переменную в вашей программе. Вы можете использовать copy() или deepcopy(), если хотите внести изменения в список в одной переменной без изменения исходного списка.

Добавить комментарий