Перечислимые типы (iterable)
Базовые перечислимые типы
Тип | Название | Объявление | Порядок |
---|---|---|---|
list | Список | [1, 2, 1], ["a", "b", "a"], [] | Да |
tuple | Кортеж | (1, 2, 1), ("a", "b", "a"), ("a",) | Да |
set | Набор | {1, 3, 2}, {"a","c","b"}, set() | Нет |
dict | Словарь | {"a":1, "c":2, "b":1}, {} | Нет |
Перечислимые типы являются изменяемыми (mutable). При присвоении переменные этих типов не копируются.
Типы tuple
, str
и bytes
имеют промежуточный статус. Они является неизменяемыми, но переменные этих типов можно перечислять.
Особенности перечислимых типов
- Элементы перечислимых типов могут быть произвольного, в том числе перечислимого типа:
data = [5,7,9,12,"test",True,["ab","cd","ef"]]
- Списки и кортежи сохраняют порядок, а наборы и словари - нет:
data_list = [5,4,3,6,2,1]
data_set = {5,4,3,6,2,1}
print(data_list) # [5, 4, 3, 6, 2, 1]
print(data_set) # {1, 2, 3, 4, 5, 6}
- Переменные перечислимых типов (как и все составных) при присвоении не копируются:
data = [5,7,9,12]
double_data = data
double_data[1] = 42
print(data) # [5, 42, 9, 12]
- Переменные перечислимых типов можно перечислять.
Итерационный цикл for
Цикл for
используется для перебора элементов в переменных перечислимых типов.
Синтаксис:
for <новая переменная> in <переменная перечислимого типа> :
␣␣␣␣<оператор>
␣␣␣␣<оператор>
Примеры:
data = ['a', 'b', 'c', 'd']
for x in data:
print(x)
Список: list
- Используется в качестве замены массивам и векторам
- Может иметь произвольную длину
- Его можно удлинять и укорачивать
Индексирование списков
Индексирование в Python выполняется с 0.
data = ['a', 'b', 'c', 'd']
data[0] # 'a'
data[3] # 'd'
data[4] # Ошибка: выход за пределы списка
# Отрицательные индексы нумеруют список с конца и с -1
data[-1] # 'd'
data[-4] # 'a'
# Длина
x = len(data) # x == 4
# Поиск по значению
x = data.index('c') # x == 2
Срезы списков
Срезы (slices) — это способ получать из списка его часть не прибегая к циклам.
Синтаксис:
<индекс первого элемента>:<индекс последнего элемента +1>
<индекс первого элемента>:<индекс последнего элемента +1>:<шаг>
data = ['a', 'b', 'c', 'd']
data[1:3] # ['b', 'c']
data[2:] # ['c', 'd']
data[:] # ['a', 'b', 'c', 'd']
data[-2:] # ['c', 'd']
data[1:4:2] # ['b', 'd']
Срезы создают копию списка.
data = ['a', 'b', 'c', 'd']
# нет копирования temp и data это один список с двумя именами
temp = data
temp[0] = 'z' # data[0] == 'z'
# есть копирование temp и data это разные списки
temp = data[:]
temp[0] = 'z' # data[0] == 'a'
Модификация списков
Изменения в самом списке:
data = ['a', 'b', 'c', 'd']
data[1] = 42 # data == ['a', 42, 'c', 'd']
del data[1] # data == ['a', 'c', 'd']
data.insert(0,42) # data == [42, 'a', 'c', 'd']
data.append(42) # data == [42, 'a', 'c', 'd', 42]
data = data + [1,2,3]
# data == [42, 'a', 'c', 'd', 42, 1, 2, 3]
v = data.pop()
# v == 3, data == [42, 'a', 'c', 'd', 42, 1, 2]
v = data.pop(0)
# v == 42, data == ['a', 'c', 'd', 42, 1, 2]
Обход списков
data = ['a', 'b', 'c', 'd']
for v in data:
print(v) # a b c d
for i,v in enumerate(data):
print(i,v) # 0 a 1 b 2 c 3 d
Если элемент списка неизменяемого типа, то при присвоение переменной созданной в цикле for
(в примере, v
) нового значение не меняет содержание массива.
i = 0
while i < len(data):
data[i] = 42
i += 1
for i in range(0,len(data)):
data[i] = 42
Явное изменение списка.
Кортеж: tuple
Кортеж это неизменяемый список.
tple = (1, 2, 3)
tple[0] # 1
tple[0] = 0 # Ошибка
tple.append(0) # Ошибка
Набор: set
Набор не сохраняет порядок. Все элементы набора различны.
vset = {4, 3, 2, 3, 1}
print(vset) # {1, 2, 3, 4}
vset[0] # Ошибка
vset.add(0) # {0, 1, 2, 3, 4}
vset.add(4) # {0, 1, 2, 3, 4}
vset.remove(4) # {0, 1, 2, 3}
Типичное применение — удаление дубликатов из списка:
data = [1, 1, 2, 2, 2]
data = list(set(data)) # [1, 2]
Словарь: dict
- Набор пар ключ-значение. Ключи всегда различны.
- Значения могут быть любого типа, ключи — с некоторыми ограничениями.
data = {"a":1, "b":2, "c":3}
data["b"] # 2
Модификация словарей
data = {"a":1, "b":2, "c":3}
data["b"] = 3 # data == {"a":1, "b":3, "c":3}
del data["b"] # data == {"a":1, "c":3}
data["f"] = 99 # data == {'a': 1, 'f': 99, 'c': 3}
x = len(data) # x == 3
data.update({"a":99, "q":64})
# data == {'a': 99, 'f': 99, 'q': 64, 'c': 3}
Обход словарей
data = {"a":1, "b":2, "c":3}
for k in data:
print(k) # a c b
print(data[k]) # 1 3 2
for k in sorted(data.keys()):
print(k,data[k]) # a 1 b 2 c 3
Копирование переменных составных типов
При присвоении переменные составных типов (и в частности перечислимых) не копируются:
data = {"a":1, "b":2, "c":3}
new_data = data
new_data["a"] = 42
print(data["a"]) # 42 !!!
Копирование переменных составных типов
Для их копирования используются срезы и методы copy
и deepcopy
из модуля copy
:
import copy
data = {"a":1, "b":2, "c":3}
new_data = copy.copy(data) # Поверхностная копия
new_data["a"] = 42
print(data["a"]) # 1
data = {"a":1, "b":[2,3,4], "c":3}
new_data = copy.deepcopy(data) # Полная копия
new_data["b"][0] = 42
print(data["b"]) # [2,3,4]
Сортировка списков
adata = [5,4,2,1,4]
# Сортировка с копированием
bdata = sorted(adata) # bdata == [1, 2, 4, 4, 5]
# Сортировка на месте (in-place)
adata.sort() # adata == [1, 2, 4, 4, 5]
# Обратная сортировка
bdata = sorted(adata, reverse=True) #[5, 4, 4, 2, 1]
adata.sort(reverse=True) #[5, 4, 4, 2, 1]
Приведение перечислимых типов
Исходный тип data |
||||
---|---|---|---|---|
Целевой тип | list | tuple | set | dict |
list | list(data) | list(data) | list(data.keys()), list(data.values()) |
|
tuple | tuple(data) | tuple(data) | tuple(data.keys()), tuple(data.values()) |
|
set | set(data) | set(data) | set(data.keys()), set(data.values()) |
|
dict | dict(zip(keys,data)) | dict(zip(keys,data)) | dict(zip(keys,data)) |