Списки могут содержать объекты любых типов (в одном списке могут быть объекты разных типов). Списки индексируются так же, как строки.
l=[0,1,2,3,4,5,6,7,8,9]
l
len(l)
l[0]
l[3]
l[10]
l[-2]
l[1:3]
Обратите внимание, что l[:3]+l[3:]==l
.
l[:3]
l[3:]
l[3:3]
l[3:-2]
l[:-2]
Списки являются изменяемыми объектами. Это сделано для эффективности. В списке может быть 1000000 элементов. Создавать его копию каждый раз, когда мы изменили один элемент, слишком дорого.
l[3]='три'
l
Можно заменить какой-нибудь подсписок на новый список (в том числе другой длины).
l[3:3]=[0]
l
l[3:3]=[10,11,12]
l
l[5:7]=[0,0,0,0]
l
l[3:]=[]
l
l[len(l):]=[3,4]
l
Некоторые из этих операций могут быть записаны в другой форме.
l=[0,1,2,3,4,5,6,7]
del l[3]
l
del l[3:5]
l
l.insert(3,0)
l
l.append(8)
l
l.extend([9,10,11])
l
Элементы списка могут быть разных типов.
l=[0,[1,2,3],'abc']
l[1][1]='x'
l
Когда мы пишем m=l
, мы присваиваем переменной m
ссылку на тот же объект, на который ссылается l
. Поэтому, изменив этот объект (список) через l
, мы увидим эти изменения и через m
- ведь список всего один.
l=[0,1,2,3,4,5]
m=l
l[3]='три'
m
Операция is
проверяет, являются ли m
и l
одним и тем же объектом.
m is l
Если мы хотим видоизменять m
и l
независимо, нужно присвоить переменной m
не список l
, а его копию. Тогда это будут два различных списка, просто в начальный момент они состоят из одних и тех же элементов. Для этого в питоне есть идиома: l[:]
- это подсписок списка l
от начала до конца, а подсписок всегда копируется.
m=l[:]
Теперь m
и l
- два независимых объекта, имеющих равные значения.
m is l
m==l
Их можно менять независимо.
l[3]=0
l
m
Как и для строк, сложение списков означает конкатенацию, а умножение на целое число - повторение списка несколько раз. Операция in
проверяет, содержится ли элемент в списке.
[0,1,2]+[3,4,5]
2*[0,1,2]
l=[0,1,2]
l+=[3,4,5]
l
2 in l
Простейший вид цикла в питоне - это цикл по элементам списка.
for x in l:
print(x)
Можно использовать цикл while
. В этом примере он выполняется, пока список l
не пуст. Этот цикл гораздо менее эффективен, чем предыдущий - в нём на каждом шаге меняется список l
. Он тут приведён не для того, чтобы ему подражали, а просто чтобы показать синтаксис цикла while
.
while l:
print(l[0])
l=l[1:]
l
Очень часто используются циклы по диапазонам целых чисел.
for i in range(4):
print(i)
Функция range(n)
возвращает диапазон целых чисел от 0 до $n-1$ (всего $n$ штук) в виде специального объекта range
, который можно использовать в for
цикле. Можно превратить этот объект в список функцией list
. Но этого делать не нужно, если только такой список не нужен для проведения каких-нибудь списковых операций. Число n
может быть равно 1000000. Зачем занимать память под длинный список, если он не нужен? Для написания цикла достаточно короткого объекта range
, который хранит только пределы.
r=range(4)
r
list(r)
Функции range
можно передать первый параметр - нижний предел.
for i in range(2,4):
print(i)
r=range(2,4)
r
list(r)
Функция list
превращает строку в список символов.
l=list('абвгд')
l
Как написать цикл, если в его теле нужно использовать и номера элементов списка, и сами эти элементы? Первая идея, которая приходит в голову по аналогии с C - это использовать range
.
for i in range(len(l)):
print(i,' ',l[i])
Можно поступить наоборот - устроить цикл по элементам списка, а индексы вычислять.
i=0
for x in l:
print(i,' ',x)
i+=1
Оба этих способа не есть идиоматический питон. Более изящно использовать функцию enumerate
, которая на каждом шаге возвращает пару из индекса i
и i
-го элемента списка.
for i,x in enumerate(l):
print(i,' ',x)
Про такие пары мы поговорим в следующем параграфе.
Довольно часто удобно использовать цикл while True:
, то есть пока рак на горе не свистнет, а выход (или несколько выходов) из него устраивать в нужном месте (или местах) при помощи break
.
while True:
print(l[-1])
l=l[:-1]
if l==[]:
break
Этот конкретный цикл - отнюдь не пример для подражания, он просто показывает синтаксис.
Можно строить список поэлементно.
l=[]
for i in range(10):
l.append(i**2)
l
Но более компактно и элегантно такой список можно создать при помощи генератора списка (list comprehension). К тому же это эффективнее - размер списка известен заранее, и не нужно много раз увеличивать его. Опытные питон-программисты используют генераторы списков везде, где это возможно (и разумно).
[i**2 for i in range(10)]
[[i,j] for i in range(3) for j in range(2)]
В генераторе списков могут присутствовать некоторые дополнительные элементы, хотя они используются реже. Например, в список-результат можно включить не все элементы.
[i**2 for i in range(10) if i!=5]
Создадим список случайных целых чисел.
from random import randint
l=[randint(0,9) for i in range(10)]
l
Функция sorted
возвращает отсортированную копию списка. Метод sort
сортирует список на месте. Им можно передать дополнительный параметр - функцию, указывающую, как сравнивать элементы.
sorted(l)
l
l.sort()
l
Аналогично, функция reversed
возвращает обращённый список (точнее говоря, некий объект, который можно использовать в for
цикле или превратить в список функцией list
). Метод reverse
обращает список на месте.
list(reversed(l))
l
l.reverse()
l
Метод split
расщепляет строку в список подстрок. По умолчанию расщепление производится по пустым промежуткам (последовательностям пробелов и символов tab
и newline
). Но можно передать ему дополнительный аргумент - подстроку-разделитель.
s='abc \t def \n ghi'
l=s.split()
l
Чтобы напечатать элементы списка через запятую или какой-нибудь другой символ (или строку), очень полезен метод join
. Он создаёт строку из всех элементов списка, разделяя их строкой-разделителем. Запрограммировать это в виде цикла было бы существенно длиннее, и такую программу было бы сложнее читать.
s=', '.join(l)
s
s.split(', ')