====== Списки, кортежи, множества, диапазоны, словари ======
===== Списки, кортежи, множества, диапазоны =====
Нумерованные наборы объектов, каждый элемент **содержит лишь ссылку на объект**, поэтому могут содержать **смесь любых типов данных** и иметь **неограниченную вложенность**.\\
Поддерживают обращение по индексу, срез, конкатенацию, повторение, проверку на вхождение (не вхождение).\\
==== Списки ====
**Изменяемый тип данных**\\
=== Создание списка ===
* **list(...)**
* **["", .. ""]**
* **.append('')**
Вложенные списки следует создавать методом **append()**\\
т.к. **хранятся ссылки**, можно **легко ошибиться** групповым присваиванием, для **создания копии** можно использовать **срез**, либо метод **copy()**, лучше **deepcopy()**\\
=== Операции над списками ===
Можно **удалить часть** списка присвоив **срезу пустое значение**\\
Элементы в обратном порядке: **arr[::-1]**, последний элемент: **arr[-1:]**\\
Обращение **за пределы индекса- исключение**\\
=== Многомерные списки ===
Элементы могут быть любого типа, в т.ч. и целыми списками\\
arr= [
[1, 2, 3, 'a']
[3, 2, 1, 'b']
[4, 5, 6, [1, 2]]
]
=== Перебор элементов списка ===
При переборе в цикле for, итератор можно изменять, но если тип данных не изменяемый, то изменения не сохранятся\\
Для генерации индексов можно использовать диапазон: **range(len(arr))**\\
Так же, есть функция **enumerate()**, возвращает кортеж из индекса и значения, текущего элемента списка\\
for i, elem in enumerate(arr):
arr[i] *= 2
=== Генераторы списков ===
Генерирует последовательность для списка, **возвращает новый**, работает быстрее цикла **for**\\
arr= [1, 2, 3, 4]
arr= [i * 2 for i in arr]
# Может иметь сложную, вложенную структуру
arr= [i * 10 for i in arr if i % 2== 0]
# Или
arr= [[1,2], [3,4], [5,6]]
arr= [i * 10 for i in arr for j in i if j % 2== 0]
>> [20,40,60]
Если выражение разместить в круглых скобах, тогда будет возвращаться не список а итератор\\
arr= [1, 4, 12, 45, 10]
sum((i for i in arr if i % 2 == 0))
>> 26
=== Фильтрация в списке ===
[[https://www.w3schools.com/python/python_lists_comprehension.asp|List Comprehension]]\\
# В новый список добавляется элемент i, если подходит под if, его можно модифицировать в начале конструкции
res = [i for i in raw_list if re.search(f".*{text}.*", i, re.I)]
#
regexp = re.compile(f".*{text}.*", re.I)
res2 = list(filter(regexp.fullmatch, raw_list))
=== zip(), map(), filter(), reduce() ===
**map()** - позволяет применить **заданную функцию к каждому элементу**, возвращает объект итерации\\
Указать можно несколько списков, передаваться будут соответствующие, при разных размерах списков, предпочтение отдается меньшему\\
**zip()** - передается несколько списков, возвращает кортеж с соответствующими элементами из каждой последовательности\\
**filter** - позволяет выполнить проверку каждого элемента последовательности, **возвращает элементы прошедшие проверку**\\
Передается функция для проверки, либо выражение, если указать **None** то будет проверка каждого элемента на **True**, несоответствующие элементы отбрасываются из результата\\
**reduce()** - применяет указанную функцию к элементам и **накапливает результат**. В функцию **передается два значения**, текущий элемент и сумма вычислений\\
print(list(map(myfunc, arr)))
print(list(zip([1,4,7], [2,5,8], [3,6,9])))
=== Добавление/удаление элементов ===
* **append()** - добавить элемент в конец
* **extend()** - добавить последовательность (список/кортеж) в конец
* + конкатенация
* + +=
* + присвоение срезу
* **insert()** - ставить элемент в указанную позицию
* **pop()** - удаляет последний либо указанный (по индексу) элемент
* **remove()** - удаляет первый по значению элемент
* **clear()** - очищает весь список
Для **удаления повторяющихся** значений можно преобразовать список во множество, затем обратно\\
=== Поиск элементов в списке и сведения о них ===
Проверка вхождения- **in** / **not in**\\
Получить индекс указанного элемента- **index()**, если его нет, будет исключение\\
Кол-во указанных значений- **count()**\\
**max()**/ **min()**\\
**any()** / **all()** - проверка элементов на True, возврат положительный если хотя бы один ==true / все ==true\\
=== Переворачивание/перемешивание ===
Метод **reverse()** переворачивает список, соответствующая ф-я делает тоже самое и возвращает результат\\
Ф-я **shuffle()** - перемешивает случайным образом\\
=== Выбор случайных элементов ===
import random
**random.choice()** - возвращает случайный элемент из любой последовательности\\
**random.sample()** - вернет список из случайных элементов входного списка\\
=== Сортировка ===
Метод **sort()** - можно указать собственную функцию для сортировки, есть аналогичная ф-я\\
=== Преобразование в строку ===
Метод **join()**, **str()**\\
==== Кортежи ====
**Не изменяемый тип данных (список)**\\
Создать можно ф-ей **tuple()**, последовательность **в круглых скобках**, точнее именно запятые формируют кортеж, а не круглые скобки, последних **может и не быть**\\
В целом, поддерживают те же методы что и списки, только это не изменяемый тип\\
==== Множества ====
Набор **уникальных значений**. Может быть как изменяемым так и не изменяемым. **set()**\\
Есть целый ряд методов для работы с парами множеств, типа разности/пересечений/конкатенаций и т.д.\\
**frozenset()**- неизменяемое множество\\
==== Диапазоны ====
Содержит только последовательные значения, формируется "на лету", занимает минимум ресурсов\\
Поддерживается сравнение диапазонов (== !=) и методы **start()**/**stop()**/**step()** возвращающие пар-ры\\
range(<Начало>=, <Конец>, <Шаг>=)
range(1, 10)
range(10, 1, -1)
range(10, 110, 10)
==== Модуль itertools ====
Ф-ции позволяющие генерировать различные последовательности, производить фильтрацию и т.д.
=== Генерирование неопределенного кол-ва значений ===
* **count(=0, =1)** - создает бесконечную последовательность. Удобно для подсчета\\
* **cycle()** - на каждой итерации возвращает очередной элемент указанной последовательности, по кругу\\
* **repeat()** - возвращает объект указанное кол-во раз\\
list(zip(itertools.count(), "abcdef"))
>> [(0, a), (1, b), (2, c), (3, d), (4, e), (5, f)]
list(zip(itertools.cycle([0,1]), "abcdef"))
>> [(0, a), (1, b), (0, c), (1, d), (0, e), (1, f)]
list(zip(itertools.repeate(5]), "abcdef"))
>> [(5, a), (5, b), (5, c), (5, d), (5, e), (5, f)]
=== Генерирование комбинаций ===
* **combinations()** - на каждой итерации возвращает кортеж, комбинаций из указанного кол-ва эл, элементы гарантированно разные\\
* **combinations_with_replacement()** - -||- ток элементы могут повторяться\\
* **permutations()** - -||- если кол-во не указано, используется длинна последовательности\\
* **product()** - -||- из одной или нескольких последовательностей\\
list(itertools.combinations('абвг', 2))
>> [('а', 'б'), ('а', 'в'), ('а', 'г'), ('б', 'в') ...]
list(itertools.combinations('абвг', 2))
>> [('а', 'б'), ('а', 'в'), ('а', 'г'), ('б', 'в') ...]
=== Фильтрация последовательности ===
Указывается пользовательская функция для проверки условия, возвращаются элементы соответствующие true/false, в зависимости от метода, разные варианты:\\
**filterfalse()**, **dropwhile()**, **takewhile()**, **compress()**\\
=== Прочие функции ===
Несколько функций для работы с последовательностями:\\
**islice()**, **starmap()**, **zip_longest()**, **accumulate()**, **chain()**, **chain.from.iterable()**, **tee**\\
===== Словари =====
Ассоциативные массивы, в качестве **ключа может быть неизменяемый** тип данных в т.ч. кортеж, сам **словарь изменяемый** тип.\\
Объекты произвольного типа, неограниченная вложенность, многие методы списков не доступны, например срез, конкатенация, повторение и т.д.\\
Фильтрация словаря (аналогично списку, генерация)\\
dict_match_graph = {name_graph: id_graph for name_graph, id_graph in dict_all_graphs.items() if re.search(input_text, name_graph, re.I)}
==== Создание словаря ====
* **dict()**
* **{}**
* **dict.fromkeys()**
* **copy(), deepcopy()**
==== Операции над словарями ====
Обращение по ключу, если элемента нет то будет исключение **KeyError**, чтобы избежать можно обращаться методом **get(, )**\\
Проверка на вхождение- **in, not in**\\
* **setdefault(, )** - если ключ отсутствует, то создастся элемент\\
* **len()**- кол-во ключей в словаре\\
* **del()**- удаляет элемент (del d['key'])\\
==== Перебор элементов словаря ====
Метод **keys()** возвращает объект с ключами, по которым можно получить доступ в цикле\\
**sort()**, **sorted()** - метод и функция для сортировки ключей
for key in sorted(d.keys()):
print("({0} - {1})".format(key, d[key]), end= '\n')
==== Методы ====
* **keys(), values(), items()**- возвращает объект содержащий соответствующую перечень данных
* **pop(), popitem(), clear()**- удаление
* **update()**- добавляет элементы в словарь, **имеющиеся ключи перезапишутся**
* **copy(), get(), setdefault(), in, not in**
==== Генераторы словарей ====
В отличии от генераторов списков, тут значение в фигурных (а не квадратных) скобках, внутри выражения два значения а не одно (ключ:значение)\\
arrkeys= ['a', 'b']
arrvalues= ['1', '2']
{k: v for (k, v) in zip(arrkeys, arrvalues)}
>> {'a':1, 'b':2}
{k:0 for k in arrkeys}
{'a':0, 'b':0}