====== Перечислимые типы (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))'' | |