****** Python ****** Описание ======== Для установки компилятора языка программирования скачайте инсталлятор соответствующий ващей операционной ссистеме с сайта разработчика Python.org_ Так же установив Python можно использовать консольные утилиты .. _Python.org: https://www.python.org/downloads/ Установка ========= Windows ------- .. code:: console choco install python3 Linux: Ubuntu ------------- .. code:: sh sudo apt install python3 Linux: Fedora ------------- .. code:: sh sudo dnf install python3 .. note:: в Linux дистрибутивах установщик пакетов pip (он нам понадобится в будущем) необходимо устанавливать дополнительно. .. code:: sh sudo apt install python3-pip Введение Интерактивная среда IDLE ------------------------ Для вызова интерактивной среды разработчика достаточно в консоли набрать команду: .. code:: sh python3 .. figure:: /_static/images/IDLE.png :figwidth: 600px :target: /_static/images/IDLE.png В этой интерактивной среде можно выполнять команды Python и сразу же получать результат выполнение введенной команды. Редакторы кода и среда разработки IDE ------------------------------------- Для написания программ на языке Python подойдет любой текстовый редактор, но для более комфортной работы рекомендуется использовать редакторы кода с подсветкой синтаксиса и отслеживанием ошибок. один из таких редакторов, это VSCODE_ Так же будет полезно использовать полноценную среду разработки IDE, одной из наиболее популярных евляется PyCharm_ Виртуальное окружение (venv) ---------------------------- Для начала работы рекомендуется подготовить виртуальное окружение, оно необходимо для того что бы вслучае использования дополнительных библиотек они не конфликтовали с другими библиотеками используемыми в других проектах, например: нет необходимости держать в одном проекте библиотеки фреймворков **Django** и **Flask** Для того что бы создать виртуальное окружение, в папке с проектом необходимо выполнить команду: .. code:: sh python -m venv venv незабудьте так же активировать ваше виртуальное окружение выполнив команду: .. code:: sh source venv/bin/activate это создаст внутри проекта папку venv с компилятором и всеми необходимыми библиотеками используемые по умолчанию. Так же для того что бы сохранить список используемых в нашем проекте библиотек, нужно создать файл reqirements.txt его можно создать автоматически выполнив команду: .. code:: sh pip freeze > requirements.txt Для установки в наше виртуальное окружение необходимых библиотек нужно выполнить команду: .. code:: sh pip install requirements.txt Попробуйте установить фреймворк **flask** используя менеджер пакетов pip и сохраните список установленных пакетов: .. code:: sh pip install flask pip freeze > requirements.txt Теперь если вы откроете файл **requirements** вы увидите список наших зависимостей используемые в нашем проекте .. code:: python click==7.1.2 Flask==1.1.2 itsdangerous==1.1.0 Jinja2==2.11.2 MarkupSafe==1.1.1 Werkzeug==1.0.1 Первая программа ---------------- Настало время написать нашу первую программу, создайте файл **Hello_World.py** со следующим содержимым: .. literalinclude:: ../../Examples/Hello_World.py :language: python Теперь запустите нашу программу выполгив в консоле команнду: .. code:: sh python Hello_World.py в консои вы должны увидеть результат нашей программы. .. note:: Обратите внимание, что первая строка указывает какой интерпритатор мы будет использовать, она необходима если мы хотим запускать нашу команду с интерпритатором по умолчанию, например так: .. code:: sh ./Hello_World.py Если этой строки не будет, то мы получим ошибку. Вторая строка отвечает за кодировку, тоесть если мы хотим вывести на экран Русские символы, то нам надо указать какую кодировку мы будем ипользовать. .. _PyCharm: https://www.jetbrains.com/pycharm/download/ .. _VSCODE: https://code.visualstudio.com Основы синтаксиса ================= Типы данных ----------- Переменные в Python: ^^^^^^^^^^^^^^^^^^^^ Переменная в языке программирования это название для зарезервированного места в памяти компьютера, предназначенное для хранения значений. Это означает, что когда вы создаете переменную, вы на самом деле резервируете определенное место в памяти компьютера. Основываясь на типе данных переменной, интерпретатор выделяет необходимое количество памяти и решает, что может находится в зарезервированной области памяти. Для понимания, можете думать о переменной как о коробке, в которую можно положить любую вещь, но только определенного размера. Размер в данном примере будет типом переменной. Это не совсем верное определение, но оно дает общее представление о картине в целом. **Основные форматы именования** snake_case (змеиный регистр) - С маленькой буквы. Все буквы строчные. Слова разделяются символом подчёркивания _. (Используется в переменных, функциях, модулях, файлов) PascalCase (Паскаль-регистр) - Каждое слово начинается с заглавной буквы. Подчёркивания не используются. (Используется в классах, исключениях) SCREAMING_SNAKE_CASE (кричащий змеиный регистр) - все буквы заглавные, слова разделяются подчёркиваниями. (Используется для констант, БД) _single_leading_underscore (одиночное подчёркивание в начале) - подчёркивание в начале означает, что элемент внутренний. (Используется для приватных переменных, методов внутри модулей, классов.) __double_leading_underscore (двойное подчёркивание в начале) - Python изменяет имя внутри класса (name mangling), чтобы предотвратить случайное переопределение при наследовании (Используется для защиты атрибутов и методов от переопределения) Форматы в других языках camelCase - верблюжий регистр kebab-case - шашлычный стиль **Полный список ключевых слов Python** Все зарезервированные имена, которые нельзя использовать как переменные, функции или классы :: False # Логическое значение False True # Логическое значение True None # Пустое значение / отсутствие значения and # Логическое "и" or # Логическое "или" not # Логическое "не" is # Проверка идентичности объектов in # Проверка принадлежности элемента последовательности if # Условный оператор elif # Иначе если else # Иначе for # Цикл for while # Цикл while break # Прерывание цикла continue # Продолжение цикла def # Определение функции return # Возврат значения из функции class # Определение класса try # Начало блока try-except except # Обработка исключений finally # Завершение блока try-except raise # Генерация исключения import # Подключение модуля from # Импорт конкретного элемента из модуля as # Псевдоним при импорте with # Контекстный менеджер lambda # Анонимная функция pass # Пустая операция yield # Возврат значения генератором global # Глобальная переменная nonlocal # Область видимости не локальная assert # Проверка условия del # Удаление объекта Как проверить в Python актуальные ключевые слова .. code:: python import keyword print(keyword.kwlist) Python чувствителен к регистру, поэтому Var, var и VAR — разные имена. Нельзя использовать для своих переменных или функций: пробелы, дефисы -, специальные символы (@, !, %, $ и т.д.) .. code:: python __init__ # Конструктор класса __str__ # Представление объекта как строки 1variable = 5 # Нельзя начинать имя с цифры # не рекомендуется переопределять встроенные функции и типы Python list = [1, 2, 3] # перезапишет встроенный list str = "Hello" # перезапишет встроенный str id = 100 # перезапишет встроенный id() **Присвоение значения переменной:** В Python вам не нужно объявлять тип переменной вручную (как, например в С++). Объявление происходит автоматически (это называется динамическая типизация), когда вы присваиваете значение переменной. Знак равенства ( = ) используется для присвоения значения переменной. Операнд по левую сторону от знака равно ( = ) это имя переменной, операнд по правую сторону - значение присвоенное этой переменной. .. code:: python # Простое присваивание x = 10 # число y = "hello" # строка z = [1, 2, 3] # список # Множественное присваивание a, b, c = 1, 2, 3 # Распаковывается в несколько переменных. data = [10, 20, 30, 40] x, y, *rest = data # x - 10, y - 20, rest - 30,40 Можно использовать * в любом месте, но только один раз. # Упаковка в кортеж t = (x, y, *rest) # Обмен значений a = 1 b = 2 a, b = b, a print(a, b) # 2 1 # Распаковка с _ для игнорируемых значений a, _, b = [1, 2, 3] print(a, b) # 1 3 **Таблица - Обзор встроенных типов объектов** +------------------------------+---------+-----------------------------------------------+ | Имя | Тип | Описание и пример | +==============================+=========+===============================================+ | Целые Числа | int | Целые положительные или отрицательные числа | | | | -35, 0, 24, 123467890033373747428 | +------------------------------+---------+-----------------------------------------------+ | Числа с плавающей точкой | float | Дробные числа 3.14, 2.5, -2.33333, 0.12334 | +------------------------------+---------+-----------------------------------------------+ | Строки | str | Строки "asdf", "Hello world", "123456" | +------------------------------+---------+-----------------------------------------------+ | Списки | list | последовательность элементов | | | | ["hello", -123, 0.34, "345"] | +------------------------------+---------+-----------------------------------------------+ | Словарь | dict | Последовательность пар элементов содержаших | | | | ключ-значение (key-value) | | | | {"Language": "Python", "Version": "3.8"} | +------------------------------+---------+-----------------------------------------------+ | Кортеж (Tuple) | tup | Неизменяемая упорядоченная последовательность| | | | элементов ("hostname", 1234, -0.45, -32) | +------------------------------+---------+-----------------------------------------------+ | Множество | set | Изменяемая неупоряоченная последовательность | | | | элементов {10, "Name", -30, 4.02, 100} | +------------------------------+---------+-----------------------------------------------+ | Булевые значения | bool | Тип данных принимающий одно из двух значений | | | | true - истина | | | | false - ложь | +------------------------------+---------+-----------------------------------------------+ Числа, округление, системы счисления ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Числа - Это не изменяемый тип данных. Числа в Python бывают трёх типов: целые, с плавающей точкой и комплексные. Примером целого числа может служить 2. Примерами чисел с плавающей точкой (или «плавающих» для краткости) могут быть 3.23 и 52.3E-4. Обозначение E показывает степени числа 10. В данном случае 52.3E-4 означает 52.3 · 10−4. Примеры комплексных чисел:(-5+4j)и(2.3-4.6j) .. note:: Нет отдельного типа ‘long int’ (длинное целое). Целые числа по умолчанию могут быть произвольной длины. Округление """""""""" .. code:: python round(2.3) # округляет число до ближайшего целого числа, и если дробная часть числа # меньше 0.5, то число округляется вниз. Таким образом, round(2.3) будет равно 2, а не 3. int(2.3+ 0.5) # всегда округляет число вниз, также будет равно 2 import math num = 2.3 rounded_num = math.ceil(num) print(rounded_num) # выводит: 3 round(number[, ndigits]) # округляет число number до ndigits знаков после запятой (по умолчанию, # до нуля знаков, то есть, до ближайшего целого) Здесь используется так # называемое "Банковское округление", то есть округление к ближайшему # чётному. Системы счисления """""""""""""""""" .. code:: python # двоичная система number = 10 # Пример числа binary_representation = bin(number) print(binary_representation) # Выводит '0b1010' # 0b является префиксом, обозначающим, что последующие цифры находятся в двоичной системе. # 0o это префикс числа, означающий восьмеричную систему счисления. # 0x этот префикс используется для шестнадцатеричных print(binary_representation[2:]) # Выводит '1010' # В восьмеричной decimal_number = 64 octal_representation = oct(decimal_number) # Возвращает '0o100' # В шестнадцатеричной decimal_number = 255 hexadecimal_representation = hex(decimal_number) # Возвращает '0xff' # A (или a) представляет число 10. # B (или b) представляет число 11. # C (или c) представляет число 12. # D (или d) представляет число 13. # E (или e) представляет число 14. # F (или f) представляет число 15. binary_number = '101' # или '0b101' decimal_number = int(binary_number, 2) # Второй параметр это 2 - двоичная, 8 - восьмеричная, 16 - шестнадцатеричная print(decimal_number) # Выведет 5 print(1_000_000_000) # Выведет 1000000000 Строки, форматирование ^^^^^^^^^^^^^^^^^^^^^^ Строки - это неизменяемая упорядоченная последовательность символов, заключенная в кавычки. Строки применяются для записи текстовой информации (скажем, вашего имени) и произвольных совокупностей байтов (наподобие содержимого файла изображения). Они являются первым примером того, что в Python называется последовательностью — позиционно упорядоченной коллекцией других объектов. Для содержащихся элементов последовательности поддерживают порядок слева направо: элементы сохраняются и извлекаются по своим относительным позициям. Строго говоря, строки представляют собой последовательности односимвольных строк. Строки можно суммировать. Тогда они объединяются в одну строку, такая операция называется "Конкатенацией строк": .. code:: python firts_string = "asdfgh" second_string = "oiuytr" print(firts_string + second_string) .. note:: В Python 3 нет ASCII-строк, потому что Unicode является надмножеством (включает в себя) ASCII. Если необходимо получить строку строго в кодировке ASCII, используйте str.encode("ascii"). По умолчанию все строки в Unicode. .. warning:: Нельзя производить арифметические операции над строкам и числами Например: "qwerty" + 3 Это вызовет ошибку, Но строки можно перемножать "#" * 10 выведет на экран строку ########## Логические и физические строки """""""""""""""""""""""""""""" Физическая строка – это то, что вы видите, когда набираете программу. Логическая строка – Логическая строка составляется из одной или нескольких физических строк. это то, что Python видит как единое предложение. Комментарии - начинается символом '#', не являющимся частью строкового литерала `;` - объединяет две логических строки в одну физическую .. code:: python # Две логических, физических строчек i=5 print(i) # Две логических строки на одной физической строке i = 5; print(i); Рекомендовано придерживаться написания одной логической строки в каждой физической строке. Использовать разделение логической строки лишь в случае очень длинных строк. ``\`` - разделяет логическую стоку на две физических .. code:: python # Явное объединением строк. s = 'Это строка. \ Это строка продолжается.' #Это строка. Это строка продолжается. print(s) #Это вторая логическая строка month_names = ['Январь', 'февраль', # Физическая строка 'Март', 'Апрель'] # Физическая строка # month_names = ['Январь', 'февраль', 'Март', 'Апрель'] - одна логическая строка Управление выводом и спецсимволы """""""""""""""""""""""""""""""" **Спецсимволы (Escape-последовательности)** .. code:: python # \n - перенос строки (newline) print("Привет\nМир") # Привет # Мир # \t - Табуляция (отступ) print("A\tB") # A B # \r - Возврат каретки (начало строки) print("123\rA") # A23 # \\ - Сам символ обратного слэша print("C:\\Python") # C:\Python # \' - Одинарная кавычка print('It\'s OK') # It's OK # \" - Двойная кавычка print("Он сказал: \"Привет!\"") # Он сказал: "Привет!" # \b - Backspace (удаляет предыдущий символ) print("ABC\bD") # ABD # \u - Юникод-символ (по коду) print('\u2764') # ❤️ **Аргументы функции print()** .. code:: python # sep - Разделитель между элементами print('A','B','C', sep='-') # A-B-C # end - Что добавляется в конце строки print('Hello', end='!') # Hello! # file - Куда выводить текст (например, в файл) print('Текст', file=open('out.txt','w')) # запись в файл # flush - Немедленно записать вывод (не ждать буфера) print('...', flush=True) Операции над последовательностями """"""""""""""""""""""""""""""""" Проверить длину с помощью встроенной функции **len()** Нумерация всех символов в строке идет с нуля 0 1 2 3 4 5. Индекс simple_string **[1]** .. code:: python simple_string = 'Spam' len(simple_string) # 4 (подсчитывает количество символов) simple_string[0] # 'S' simple_string[1] # 'p' Если нужно обратиться к какому-то по счету символу, начиная с конца, то можно указывать отрицательные значения (на этот раз с единицы). .. code:: python simple_string = "StringBody" simple_string[1] # t simple_string[-1] # y Кроме обращения к конкретному символу, можно делать срезы строк, указав диапазон номеров (срез выполняется по второе число, не включая его): .. code:: python example_string = "Lorem Ipsum is simply dummy text of the printing and typesetting" example_string[0:9] # 'Lorem Ips' example_string[10:22] # 'm is simply ' # Если не указывается второе число, то срез будет до конца строки: example_string[-3:] # 'ing' Также в срезе можно указывать шаг: .. code:: python # Так можно получить нечетные числа a = '0123456789' a[1::2] # '13579' # А таким образом можно получить все четные числа строки a: a[::2] # '02468' # Срезы также можно использовать для получения строки в обратном порядке: a[::-1] # '9876543210' .. code:: python # Переворот строки num = input() # 12345 num_rev = num[::-1] # 54321 # Разделение строки text = "Пример строки" for char in text: print(char) # Разделение строки, с переводом в список characters = list(text) print(characters) Методы для работы со строками """"""""""""""""""""""""""""" **Методы upper, lower, swapcase, capitalize** Методы выполняют преобразование регистра строки: .. code:: python string1 = 'FastEthernet' string1.upper() #'FASTETHERNET' string1.lower() #'fastethernet' string1.swapcase() #'fASTeTHERNET' string2 = 'tunnel 0' string2.capitalize() #'Tunnel 0' # Очень важно обращать внимание на то, что часто методы возвращают преобразованную строку # и значит, надо не забыть присвоить ее какой-то переменной (можно той же). string1 = string1.upper() print(string1) #FASTETHERNET **Метод count** Метод используется подсчета, сколько раз символ или подстрока встречаются в строке: .. code:: python string1 = 'Hello, hello, hello, hello' string1.count('hello') # 3 string1.count('ello') # 4 string1.count('l') # 8 **Метод find** Методу можно передать подстроку или символ, и он покажет, на какой позиции находится первый символ подстроки (для первого совпадения): .. code:: python string1 = 'interface FastEthernet0/1' string1.find('Fast') # 10 string1[string1.find('Fast')::] # 'FastEthernet0/1' **Методы startswith, endswith** Проверка, начинается или заканчивается ли строка на определенные символы: .. code:: python string1 = 'FastEthernet0/1' string1.startswith('Fast') # True string1.startswith('fast') # False string1.endswith('0/1') # True string1.endswith('0/2') # False **Метод replace** Замена последовательности символов в строке на другую последовательность: .. code:: python string1 = 'FastEthernet0/1' string1.replace('Fast', 'Gigabit') # 'GigabitEthernet0/1' **Метод strip** Часто при обработке файла файл открывается построчно. Но в конце каждой строки или в начале , как правило, есть какие-то спецсимволы, например, перевод строки. По умолчанию метод strip() убирает пробельные символы. В этот набор символов входят: \t\n\r\f\v .. code:: python string1 = '\n\tinterface FastEthernet0/1\n' print(string1) # (перевод строки \n) #interface FastEthernet0/1 # (перевод строки \n) string1.strip() #'interface FastEthernet0/1' - удаляет спецсимволы в начале и в конце строки " hello ".strip() # 'hello' .. code:: python #Методу strip можно передать как аргумент любые символы "---hello***".strip("-*") # 'hello' lstrip() удаление символов с лева rstrip() удаление символов с права **Метод split** Метод разбивает строку на части, используя как разделитель какой-то символ (или символы) и возвращает список строк: .. code:: python string1 = 'switchport trunk allowed vlan 10,20,30,100-200' commands = string1.split() print(commands) # ['switchport', 'trunk', 'allowed', 'vlan', '10,20,30,100-200'] # По умолчанию в качестве разделителя используются пробельные символы (пробелы, табы, перевод строки), # но в скобках можно указать любой разделитель: vlans = commands[-1].split(',') print(vlans) #['10', '20', '30', '100-200'] **Метод join** Метод позволяет объединить список, кортеж или словарь в строку разделяя ее элементы другой строкой. .. code:: python myTuple = ("John", "Peter", "Vicky") x = "-".join(myTuple) print(x) #John-Peter-Vicky **Метод format** Метод позволяет подставлять в отмеченные в строке области символами "{}" значения из списка аргументов например: .. code:: python price = 49 txt = "The price is {} dollars" print(txt.format(price)) Так же можно указать тип подставляемых значений: .. code:: python #Строковые значения '{} {}'.format('one', 'two') # Подставляет строки по порядку: 'one two' #Числовые значения '{} {}'.format(1, 2) # Подставляет числа по порядку: '1 2' #Порядок значений можно указывать '{1} {0}'.format('one', 'two') # Подставляет второй аргумент первым и первый вторым: 'two one' #Можно так же подставлять значения классов class Data(object): def __str__(self): return 'str' # Возвращает «читаемое» строковое представление объекта def __repr__(self): return 'repr' # Возвращает «официальное» представление объекта '{0!s} {0!r}'.format(Data()) # !s вызывает __str__, !r вызывает __repr__: 'str repr' # Отступы и выравнивания # По правому краю, ширина 10 '{:>10}'.format('test') # ' test' (6 пробелов + 'test') # По левому краю, ширина 10, заполняется '_' '{:_<10}'.format('test') # 'test______' # По центру, ширина 10 '{:^10}'.format('test') # ' test ' (по 3 пробела слева и справа) # Срезы строк '{:.5}'.format('xylophone') # 'xylop' (берем первые 5 символов) # Срезы и отступы одновременно '{:10.5}'.format('xylophone') # 'xylop ' (срез до 5 символов + выравнивание по левому краю до ширины 10) # Числа '{:d}'.format(42) # '42' (целое число) '{:f}'.format(3.141592653589793) # '3.141593' (число с плавающей точкой, 6 знаков после запятой по умолчанию) # Числа и отступы '{:4d}'.format(42) # ' 42' (ширина 4, добавлены пробелы слева) '{:06.2f}'.format(3.141592653589793) # '003.14' (ширина 6, 2 знака после запятой, заполняем нулями) '{:04d}'.format(42) # '0042' (ширина 4, заполняем нулями) # Знаковые числа '{:+d}'.format(42) # '+42' (показываем знак числа) '{: d}'.format(-23) # '-23' (отступ перед положительным числом не нужен, знак сохраняется для отрицательного) '{: d}'.format(42) # ' 42' (пробел перед положительным числом) '{:=5d}'.format(-23) # '- 23' (минус слева, числа справа, ширина 5) '{:=+5d}'.format(23) # '+ 23' (плюс слева, числа справа, ширина 5) # Можно вставлять значения по именам data = {'first': 'Hodor', 'last': 'Hodor!'} '{first} {last}'.format(**data) # 'Hodor Hodor!' (распаковка словаря по ключам) '{first} {last}'.format(first='Hodor', last='Hodor!') # 'Hodor Hodor!' (явное именование аргументов) # Формат даты и времени from datetime import datetime '{:%Y-%m-%d %H:%M}'.format(datetime(2001, 2, 3, 4, 5)) # '2001-02-03 04:05' (форматирование даты и времени) другие примеры форматированного вывода можно найти по следующим ссылкам pyformat.info_ w3schools.com_ Преобразования и Форматирование: .. code:: python capitalize(): #Преобразует первый символ в верхний регистр. casefold(): #Преобразует строку к нижнему регистру для нечувствительного к регистру сравнения. lower(): #Преобразует все символы в нижний регистр. upper(): #Преобразует все символы в верхний регистр. if i.upper() - возвращают преобразованную строку, а не булево значение. title(): #Преобразует первый символ каждого слова в верхний регистр. swapcase(): #Меняет регистр каждого символа на противоположный. format(): #Форматирует строку. f'{} текс' format_map(): #Форматирует строку, используя словарь. Обрезка и Выравнивание: .. code:: python strip(): #Удаляет пробелы в начале и в конце строки. rstrip(): #Удаляет пробелы в конце строки. lstrip(): #Удаляет пробелы в начале строки. center(): #Выравнивает строку по центру. ljust(): #Выравнивает строку по левому краю. rjust(): #Выравнивает строку по правому краю. zfill(): #Дополняет строку нулями слева до указанной длины. Поиск и Замена: .. code:: python count(): #Считает количество вхождений подстроки. endswith(): #Проверяет, заканчивается ли строка указанной подстрокой. startswith(): #Проверяет, начинается ли строка с указанной подстроки. find(): #Находит первое вхождение подстроки. Если строка не найдена, метод вернет -1. rfind(): #Находит последнее вхождение подстроки. index(): #Похож на find, но вызывает ошибку, если подстрока не найдена. rindex(): #Похож на rfind, но вызывает ошибку, если подстрока не найдена. replace(): #Заменяет одну подстроку на другую. Разделение и Объединение: .. code:: python split(): #Разделяет строку на список строк по разделителю. rsplit(): #Разделяет строку на список строк по разделителю справа налево. splitlines(): #Разделяет строку на список строк по символам новой строки. join(): #Объединяет коллекцию строк в одну строку с разделителем. partition(): #Разбивает строку на три части по разделителю. rpartition(): #Разбивает строку на три части по разделителю справа налево. Проверки и Валидация: .. code:: python isalnum(): #Проверяет, состоит ли строка только из буквенно-цифровых символов. isalpha(): #Проверяет, состоит ли строка только из букв. isdigit(): #Проверяет, состоит ли строка только из цифр. isdecimal(): #Проверяет, состоит ли строка только из десятичных цифр. isnumeric(): #Проверяет, состоит ли строка только из числовых символов. isidentifier(): #Проверяет, является ли строка допустимым идентификатором. isspace(): #Проверяет, состоит ли строка только из пробельных символов. islower(): #Проверяет, написана ли строка в нижнем регистре. isupper(): #Проверяет, написана ли строка в верхнем регистре. istitle(): #Проверяет, написана ли строка в виде заголовка. isprintable(): #Проверяет, состоит ли строка только из печатаемых символов. isascii(): #Проверяет, состоят ли все символы строки из ASCII. Прочие: .. code:: python encode(): #Кодирует строку в указанной кодировке. expandtabs(tabsize=8): #Заменяет символы табуляции на пробелы. translate(): #Выполняет замену символов в строке на основе заданной таблицы замен. .. _pyformat.info: https://pyformat.info .. _w3schools.com: https://www.w3schools.com/python/python_string_formatting.asp **Интернирование** Это процесс, при котором одна и та же строка хранится в памяти только в одном экземпляре, чтобы избежать излишнего расхода памяти, особенно когда строки повторяются или часто используются в коде. Это сделано для того, чтобы сэкономить память и оптимизировать производительность. Если строки используются часто и они короткие, то нет смысла держать несколько одинаковых объектов в памяти. .. code:: python # Если одинаковые строки имеет меньше 5 символов то они ссылаются на одну ячейку памяти # Если больше 20 то создаются две ячейки памяти a = 'Стр' b = 'Стр' print(a is b) #True a = 'Строка которая имеет более 20 символов ASCII' b = 'Строка которая имеет более 20 символов ASCII' print(a is b) #False НЕ интернирована (динамическая строка) .. code:: python a = 'Стр'+'ока' # динамическая строка .. code:: python print(r'C:\some\name') # C:\some\name - r убирает экранирование print('some\name') # some # ame rew2 = ('два' '666') print(rew2) # два666 - объединяет две строчки рядом стоящие T-строки """""""" Списки ^^^^^^ Списки – это изменяемые упорядоченные последовательности произвольных объектов. Списки создаются посредством заключения элементов списка в квадратные скобки. Списки могут содержать объекты любого типа, числа, строки, другие списки .. code-block:: python names = [1,"Dave",3.14, ["Mark", 7, 9, [100,101]], 10] # разные типы данных. Элементы списка индексируются целыми числами, первый элемент списка имеет индекс, равный нулю. Для доступа к отдельным элементам списка используется оператор индексирования .. code-block:: python a = names[2] # Вернет третий элемент списка, "Ann" names[0] = "Jeff" # Запишет имя "Jeff" в первый элемент списка .. code:: python my_list = ['Список', 2, True] # разные типы данных. my_list2 = [True, 2, 'Список'] print(my_list == my_list2) # Возвращает False так как очередность важна. my = [] # Будет ровняться False my2 = [ # при передачи данных с сервера ил на сервер { 'us_id': 123 'us_nm': 'Red' }, { 'us_id': 65 'us_nm': 'Green' } ] sp = my_list + my_list2 # Объединяет списки Индексы и срезы: С помощью оператора среза ":" можно извлекать и изменять целые фрагменты списков: .. code:: python my_list = ['Список', 2, True] my_list[1] = 3 # Перезапись значения индекса 1 del my_list[0] # Удалит элемент списка print(my2[0]['us_id']) # выведет значение по ключу когда в списке словарь my_list[0] # Выведет 'Список' my_list[-1] # Выведет True s = [1, 2, 3, 4, 5, 6, 7, 8, 9] r = s[:2] # 1, 2 r = s[1:-1] # 2, 3, 4, 5, 6, 7, 8, 9 r = s[-2:] # 8, 9 example_string = "Lorem Ipsum typesetting" example_string[0:9] # 'Lorem Ips' example_string[-3:] # 'ing' -1 это последний элемент # Так можно получить нечетные числа a = '0123456789' a[1::2] # '13579' # А таким образом можно получить все четные числа строки a: a[::2] # '02468' # Срезы также можно использовать для получения строки в обратном порядке: a[::-1] # '9876543210' rew2 = "Привет бандит" print(rew2[50:70]) # - вернет пустоту rew2 = "Привет бандит" print(rew2[3:70]) # вет бандит [1,2,3] + [4,5] # Создаст список [1,2,3,4,5] Методы для работы со списками """"""""""""""""""""""""""""" .. code:: python l = list() # создаст пустой список s = list('1234567890') # [1,2,3,4,5,6,7,8,9] s.append(10) # Добавляет элемент в конец списка s.insert(2, 8) # Вставляет объект перед индексом. Аргумент №1 = индекс, №2 - значение s.clear() # Очищает список s.reverse() # Переворачивает список s.pop(0) # Удаляет элемент, если нет аргумента pop() удалит последний элемент s.pop(0) # Удаляет последний элемент elem = s.pop(0) # Возвращает при удалении элемента s.sort() # Сортирует по возрастанию s.sort(reverse = True) # Сортирует по убыванию s.copy() # Копирует список s.count(5) # Выведет сколько раз встречается этот элемент в списке s.remove("2") # Удаляет указанный элемент и не возвращает удаленный элемент s.index() # Возвращает позицию первого вхождения элемента s.extend('abcd') # Расширение списка [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd'] s.extend(l) # Объединить два списка Конвертация: .. code:: python s = 'Конвертирует строку в список' sl = list(s) # ['К', 'о', 'н', 'в', 'е', 'р', 'т', 'и', 'р', 'у', 'е', 'т', ' ', 'в', ' ', # 'с', 'т', 'р', 'о', 'к', 'у', ' ','в' , ' ', 'с', 'п', 'и', 'с', 'о', 'к'] sl = {'a': 10, 'f': True} # Преобразование словаря в список slk = list(sl) # ['a', 'f'] a = ['10', '20', '30'] print(','.join(a)) # 10,20,30 Арифметические операции: .. code:: python s = [1, 2, 3, 4, 5, 6] min(s) # 1 max(s) # 6 sum(s) # 21 sum(s) / len(s) # 3.5 среднее значение в списке Копирование: .. code:: python s = [1, 2, 3, 4] r = s # не копирует а ссылается на память где стоит изначальный список. Копирование по ссылке print(id(s) == id(r)) # True r = s[:] # Новый список (новый объект) r = list(s) # Новый список (новый объект) s.copy() # Копирует список, методом создания нового списка Распаковка: .. code:: python s = [1, 2, 3, 4] a, b, c, d = s # Распаковка по переменным a, *d = s # a = 1 d = [2, 3, 4] us = ['list', 23] def us_inf(name, qty): # Передача позиционных аргументов if not qty: return f'{name} просто текст' return f'{name} просто текст {qty}' print(us_inf(*us)) # * Распаковывает в 2 разных аргумента. # Метод split string1 = 'switchport trunk allowed vlan 10,20,30,100-200' commands = string1.split() print(commands) # ['switchport', 'trunk', 'allowed', 'vlan', '10,20,30,100-200'] #По умолчанию в качестве разделителя используются пробельные символы (пробелы, табы, перевод строки), #но в скобках можно указать любой разделитель: vlans = commands[-1].split(',') print(vlans) #['10', '20', '30', '100-200'] #Метод join() позволяет объеденить список, кортеж или словарь в строку разделяя ее елементы другой строкой. myTuple = ["John", "Peter", "Vicky"] x = "-".join(myTuple) print(x) #John-Peter-Vicky Словари ^^^^^^^ Словарь (dict) — это изменяемая структура данных вида ключ → значение, где: доступ идёт по ключу порядок элементов сохраняется ключи — только неизменяемые типы (строки, числа, кортежи) значения — любые типы можно добавлять, менять и удалять элементы .. code:: python london = { 'id': 1, # id -ключ, 1 - значение 'name':'London', 'it_vlan':320, 'user_vlan':1010, 'mngmt_vlan':99, 'to_name': None, 'to_id': None, 'port':'G1/0/11' } Для того, чтобы получить значение из словаря, надо обратиться по ключу: .. code:: python london = {'name': 'London1', 'location': 'London Str'} print(london['name'], london['location']) #'London1' 'London Str' Словари записываются в фигурных скобках и содержат пары ключ: значение. Они удобны, когда нужно связать набор данных с именованными ключами, например, описать свойства объекта. .. code:: python color = 'color' # строка неизменяемые данные D = {'food': 'Spam', 'quantity': 4, color: 'pink'} # переменая может быть ключем если в ней неизменяемые данные Мы можем индексировать этот словарь по ключу, чтобы извлекать и изменять зна­ чения, связанные с ключами. Операция индексации словаря имеет такой же синтак­сис, как для последовательностей, но элементом вквадратных скобках будет ключ, а не относительная позиция: .. code:: python D['food'] # Извлечь значение, связанное с ключом 'food' 'Spam' D['quantity'] += 1 # Добавить 1 к значению, связанному с ключом 'quantity' print(D) #{'color': 'pink', 'food': 'Spam', 'quantity': 5} Хотя словари часто создают сразу в фигурных скобках, на практике их нередко заполняют постепенно во время работы программы. Можно начать с пустого словаря и добавлять элементы по ключу — если ключа ещё нет, он создаётся автоматически. .. code:: python D = {} D['name'] = 'Bob' D['job'] = 'dev' D['age'] =40 print (D) #{'*:age 40, 'job': 'dev', 'name': 'Bob'} print(D['name']) #Bob В словаре в качестве значения можно использовать словарь: .. code:: python london_co = { 'r1': { 'hostname': 'london_r1', 'location': '21 New Globe Walk', 'vendor': 'Cisco', 'model': '4451', 'ios': '15.4', 'ip': '10.255.0.1' }, 'r2': { 'hostname': 'london_r2', 'location': '21 New Globe Walk', 'vendor': 'Cisco', 'model': '4451', 'ios': '15.4', 'ip': '10.255.0.2' }, 'sw1': { 'hostname': 'london_sw1', 'location': '21 New Globe Walk', 'vendor': 'Cisco', 'model': '3850', 'ios': '3.6.XE', 'ip': '10.255.0.101' } } # Доступ к данным вложенного словаря london_co['r1']['ios'] #'15.4' london_co['r1']['model'] #'4451' london_co['sw1']['ip'] #'10.255.0.101' .. code:: python # Сравнение словарей my_dict = {'1': 'get', 'res': 'get', 'wed': 'gas',} my_dict2 = {'res': 'get', '1': 'get', 'wed': 'gas',} print(my_dict == my_dict2) # True print(id(my_dict) == id(my_dict2)) # False разные объекты # Изменение словаря my_dict2['res'] = 7000 # Изменение значения my_dict2['is_new'] = True # Добавления ключа и значения, если такой ключ есть то перепишет значение del my_dict2['is_new'] # удаление ключа # Безопасное получение значения print(my_dict2['eslinetklucha']) # Если нет ключа выдаст ошибку KeyError print(my_dict2.get('eslinetklucha')) # Если нет ключа вернет None ошибки не будет print(my_dict2.get('eslinetklucha', 'Нет ключа')) # Если нет ключа вернет второй аргумент 'Нет ключа' # Просмотр содержимого print(my_dict2.items()) # Вызывает экземпляр класса виде кортеджей в списке print(my_dict2.keys()) # Вызывает ключи не в списке, конвертация list() print(my_dict2.popitem()) # Удаление последний добавленный ключ элемента # Удаление элементов dmy_dict2.popitem() # удалить последний добавленный ключ del my_dict2['res'] # удалить по ключу # Копирование словаря print(my_dict2.copy()) # Копия, если не надо изменять оригинал # Преобразование в словарь my_list =[['first', 0], ['two', 2]] my_dict = dict(my_list) # Конвертация из списка в словарь # Распаковка my_dict = {'1': 'get', 'res': 'get',} red = { # Важна последовательность распаковки и ключа. так как может перезаписать ключ как в первом так и во втором значении **my_dict # Распаковывает словарь my_dict (два ключа и 2 значения) 'wed': 'gas', # Если есть такой ключ то значение перезапишут } # Объединение словарей my = {**my_dict, **red} my = my_dict | red # Объединение словарей. Важна последовательность если одинаковые ключи Методы для работы со словарями """""""""""""""""""""""""""""" **clear()** - позволяет очистить словарь: .. code::python london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'model': '4451', 'ios': '15.4'} london.clear() print(london) #{} **copy()** - создает полную копию словаря .. code:: python london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'} london2 = london.copy() id(london) #25524512 id(london2) #25563296 london['vendor'] = 'Juniper' london2['vendor'] #'Cisco' .. note:: Если указать, что один словарь равен другому, то london2 будет ссылкой на словарь. И при изменениях словаря london меняется и словарь london2, так как это ссылки на один и тот же объект. **get()** - запрашивает ключ, и если его нет, вместо ошибки возвращает None. .. code:: python london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'} print(london.get('ios')) #None #Метод get() позволяет также указывать другое значение вместо None print(london.get('ios', 'Ooops')) #Ooops **setdefault()** - ищет ключ, и если его нет, вместо ошибки создает ключ со значением None, если ключ есть, setdefault возвращает значение, которое ему соответствует: .. code:: python london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'} ios = london.setdefault('ios') print(ios) #None london #{'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'ios': None} london.setdefault('name') #'London1' #Второй аргумент позволяет указать, какое значение должно соответствовать ключу model = london.setdefault('model', 'Cisco3580') print(model) #Cisco3580 london {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'ios': None, 'model': 'Cisco3580'} # Метод setdefault заменяет такую конструкцию: if key in london: value = london[key] else: london[key] = 'somevalue' value = london[key] **keys(), values(), items()** Все три метода возвращают специальные объекты view, которые отображают ключи, значения и пары ключ-значение словаря соответственно. Очень важная особенность view заключается в том, что они меняются вместе с изменением словаря. И фактически они лишь дают способ посмотреть на соответствующие объекты, но не создают их копию. .. code:: python london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'} keys = london.keys() print(keys) #dict_keys(['name', 'location', 'vendor']) #Сейчас переменной keys соответствует view dict_keys, в котором три ключа: name, location и vendor. #Но, если мы добавим в словарь еще одну пару ключ-значение, объект keys тоже поменяется: london['ip'] = '10.1.1.1' keys #dict_keys(['name', 'location', 'vendor', 'ip']) #Если нужно получить обычный список ключей, который не будет меняться с изменениями словаря, достаточно конвертировать view в список: list_keys = list(london.keys()) list_keys #['name', 'location', 'vendor', 'ip'] **del()** Удаляет ключ и значение .. code:: python london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco'} del london['name'] london #{'location': 'London Str', 'vendor': 'Cisco'} **update()** Позволяет добавлять в словарь содержимое другого словаря: .. code:: python r1 = {'name': 'London1', 'location': 'London Str'} r1.update({'vendor': 'Cisco', 'ios':'15.2'}) r1 # {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'ios': '15.2'} #Аналогичным образом можно обновить значения: r1.update({'name': 'london-r1', 'ios':'15.4'}) r1 ''' {'name': 'london-r1', 'location': 'London Str', 'vendor': 'Cisco', 'ios': '15.4'} ''' Кортежи ^^^^^^^ Объект кортежа нельзя изменять — кортежи являются последовательностями. Функционально они используются для представления фиксированных коллекций элементов: скажем, компонентов специфической даты в календаре. Синтаксически записываются в круглых, а не квадратных скобках и поддерживают произвольные типы, произвольное вложение и обычные операции над последовательностями: .. code:: python T = (1, 2, 3, 4) # Кортеж из 4 элементов len(Т) # Длина 4 Т + (5, б) # Конкатенация (1, 2, 3, 4, 5, 6) Т[О] # Индексация, нарезание и т.д. tuple2 = ('password',) # в одноэлементные кортежи необходимо добавлять запятую .. note:: Главное отличие кортежей заключается в том, что после создания их нельзя из­ менять, т.е. они являются неизменяемыми последовательностями. На практике кортежи применяются в целом не так часто, как списки, но весь смысл в их неизменяемости. Если вы передаете коллекцию объектов внутри своей программы в виде списка, тогда он может быть модифицирован где угодно; если вы используете кортеж, то изменить его не удастся. То есть кортежи обеспечивают своего рода ограничение целостности, что удобно в программах, крупнее тех, которые мы будем писать здесь. .. code:: python my_tuple = (1, 2, 3, ) my_tuple2 = (3, 2, 1, ) print(my_tuple == my_tuple2) # False разная последовательность значения print(my_tuple[0]) # Взятие элемента по индексу (неудобно и легко ошибиться.) Методы .. code:: python my_tuple = (1, [2, 1], 3, 1) print(my_tuple.count(1)) # 1 Количество элементов в кортеже, непоказывает во вложеных print(my_tuple.index(1) # Возвращает индекс найденного первого элемента print(my_tuple.index(1, 3+1) # второй аргумент, с какого индекса искать tuple(list(my_tuple)) # Ковертируем кортеж в список, меняем значение, и конвертируем в картеж my_dict = {'1': 'get', 'res': 'get', 'wed': 'gas',} print(tuple(my_dict)) # ('1', 'res', 'wed') конверирование списка в кортеж, выдаст кортеж из ключей my_type = (1, 2, 3) my_type2 = ('a', 'b', 'c') print(my_type + my_type2) # Объединяет кортежи Именованные кортежи """"""""""""""""""" Именованные кортежи (namedtuple) — это особый вид кортежей в Python, который позволяет обращаться к элементам по имени, а не только по индексу. .. code:: python # Модуль collections входит в стандартную библиотеку Python from collections import namedtuple # Импортируем функцию namedtuple из модуля collections Person = namedtuple("Person", ["name", "age", "job"]) # Создаём новый тип данных 'Person' с именованными полями: name, age, job # Это позволяет хранить связанные данные в объекте с доступом по имени, а не по индексу person = Person("Mike", 25, "Programmer") # Создаём экземпляр типа Person с конкретными значениями полей # В нашем случае: name="Mike", age=25, job="Programmer" print(person.age) # 25 print(person.name) # Mike # --- Получаем список полей --- print(person._fields) # ('name', 'age', 'job') # --- Преобразование в словарь --- person_dict = person._asdict() print(person_dict) # {'name': 'Mike', 'age': 25, 'job': 'Programmer'} # --- Создание нового экземпляра с изменённым полем --- # namedtuple неизменяем, поэтому для "изменения" создаём новый экземпляр new_person = person._replace(age=30) print(new_person) # Person(name='Mike', age=30, job='Programmer') # --- Разложение на переменные (распаковка) --- name, age, job = person print(name, age, job) # Mike 25 Programmer # --- Получаем значения как обычный кортеж --- tuple_person = tuple(person) print(tuple_person) # ('Mike', 25, 'Programmer') # --- Проверка неизменяемости --- try: person.age = 26 # Ошибка! namedtuple неизменяемый except AttributeError as e: print(e) # "can't set attribute" # Сортируем по возрасту people_sorted = sorted(people, key=lambda p: p.age) for p in people_sorted: print(p.name, p.age) Именованные кортежи подходят, когда нужно: хранить простые структуры данных иметь ясные имена полей но при этом не создавать полноценные классы и сохранить скорость и малую память, как у кортежей Например: координаты, параметры, настройки, результаты вычислений и т.д. Множество ^^^^^^^^^ Множество(набор) - это изменяемый неупорядоченный тип данных. В множестве всегда содержатся только уникальные элементы. Множество в Python - это последовательность элементов, которые разделены между собой запятой и заключены в фигурные скобки. С помощью множества можно легко убрать повторяющиеся элементы: .. code:: python my_set = set() # Создание пустого набора cities = ['Санкт-Петербург', 'Хабаровск', 'Казань', 'Санкт-Петербург', 'Казань'] un_cities = set(cities) for city in un_cities: print("Один мой друг живёт в городе " + city) # Один мой друг живёт в городе Хабаровск # Один мой друг живёт в городе Санкт-Петербург # Один мой друг живёт в городе Казань Множества полезны тем, что с ними можно делать различные операции и находить объединение множеств, пересечение и так далее. Объединение множеств можно получить с помощью метода union() или оператора "|": .. code:: python my_set2 = {[1], [2], 3} #TypeError в наборе не могут находится изменяемые элементы # Объединение уникальные элементы vlans1 = {10,20,30,50,100} vlans2 = {100,101,102,102,200} vlans1.union(vlans2) #{10, 20, 30, 50, 100, 101, 102, 200} vlans1 | vlans2 #{10, 20, 30, 50, 100, 101, 102, 200} #Пересечение множеств можно получить с помощью метода intersection() или оператора & vlans1 = {10,20,30,50,100} vlans2 = {100,101,102,102,200} vlans1.intersection(vlans2) #{100} # Выводит повторяющие элементы vlans1 & vlans2 #{100} # Выводит повторяющие элементы Методы .. code:: python .difference() # разница между множествами .discard() # Удаляет множества .copy() # Удаляет множества .symmetric_difference() # Выдаст элементы отсутствующих в другом множестве и пересечении .. warning:: Нельзя создать пустое множество с помощью {} (так как в таком случае это будет не множество, а словарь): set1 = {} # создается пустой словарь type(set1) # dict set2 = set() # создается пустое множество type(set2) # set Методы для работы с множествами """"""""""""""""""""""""""""""" **add()** добавляет элемент во множество: .. code:: python set1 = {10,20,30,40} set1.add(50) set1 #{10, 20, 30, 40, 50} **discard()** позволяет удалять элементы, не выдавая ошибку, если элемента в множестве нет .. code:: python set1 #{10, 20, 30, 40, 50} set1.discard(55) set1 #{10, 20, 30, 40, 50} set1.discard(50) set1 #{10, 20, 30, 40} **clear()** очищает множество .. code:: python set1 = {10,20,30,40} set1.clear() set1 #set() Булевы значения ^^^^^^^^^^^^^^^ Булевы значения это две константы True - истина и False - лож. Истинное значение: .. code:: python 1 # True - Короткая запись истины 1 print(bool(10)) # True - любое ненулевое число print(bool('abc')) # True - любая непустая строка print(bool([1, 2])) # True - любой непустой объект print([] == []) # Выражение print(100>10) # True первое число больше второго print('long string'>'Long') # True первая сторока больше второй Ложное значение: .. code:: python 1 # False - Короткая запись лож 0 print(bool(None)) # False None - без значения print(bool("")) # False Пустая строка, список, кортедж и т.д. Остальные истинные и ложные значения, как правило, логически следуют из условия. Для проверки булевого значения объекта, можно воспользоваться bool: .. code:: python items = [1, 2, 3] empty_list = [] bool(empty_list) #False bool(items) #True bool(0) #False bool(1) #True Лексикографическое сравнение строк в Python Строки сравниваются посимвольно, по Unicode-кодам. Если первые символы одинаковы, Python сравнивает следующие, пока не найдёт различие .. code:: python print('long string' > 'Long') # True print('long string' > 'Short') #True Первый символ 'l' (код 108) и 'S' (код 83). Поскольку 108 > 83, # Python сразу решает, что строка 'long string' больше, чем 'Short', и не продолжает сравнение дальше. print('long' > 'long') # False print('a' > 'at') # False Сначала сравнивается первый символ обеих строк — 'a' и 'a' Строка 'a' не имеет второго символа, а строка 'at' имеет 't' на второй позиции. # поскольку строка 'a' короче, чем 'at', Python считает её меньшей, и результат сравнения будет False print('long string' > 'Short string') # True Строки сравниваются на основе их символов, используя их числовые коды (Unicode). # 'l' (номер в Unicode 108) и 'S' (номер 83). 108 > 83 print('long' == 'long') # True print('long string' == 'Long string') # False учитывает регистр print('Long string' == 'Short string') # False учитывает значение print('Long string' == 'Long string') # False учитывает пробел Анатация типов -------------- Аннотации типов просто считываются интерпретатором Python и никак более не обрабатываются, но доступны для использования из стороннего кода и в первую очередь рассчитаны для использования статическими анализаторами. Аннотации типов поддерживаются многими IDE для Python, которые выделяют некорректный код или выдают подсказки в процессе набора текста. .. code:: python cnt: int # Указыет, переменая должна быть int cnt: str # Трезаписывает, тип анатации переменой на str cnt: int = 0 # при наведении курсора на переменую, IDE(VS-Code) показывает тип переменой def mul2(x: int, y: int = 2 ) -> float: # x: int, y: int = 2 - по умолчанию -> float - вывод типа ter: str = 'a' return x * y res = mul2(1) print(res) print(mul2.__annotations__) # {'x': } - проверка типа анатации from typung import Unio, Optional, Any, Final sev: Union[int, float] = 1 # Unio - это int или float sev: int | float = 1 # Тоже самое с Python 3.10 Digit = Union[int, float] # Псевдоним типа (type alias), поэтому имя пишется с большой буквы по принятому соглашению sev: Digit = 1 Str = Optional[str] # Тоже самое что и StrTyp = Union[str, None] sev: Any = 1 # Any - любой тип данных MAX_VALUE: Final = 1000 # Final - Присвоение константы from typung import List, Tuple, Dict, Set, Callable lst: list = [1, 2, '3', True] # Анатация списка lst: list[int] = [1, 2, '3', True] # Анатация списка с типом в списке, модуль mypy отлавливает ошибку addr: tuple[int, str] = (1, 'ds', 3) # Указывается тип у каждого элемента elems: tuple[float, ...] = [1.2, 2.3] # Все элементы должны быть float # словари, str -ключи, int - значения words: dict[str, int] = {'one': 1} # колекция pers: set[str] = {'dds', 'dfs'} # Callable описывает контракт функции: какие аргументы она принимает и что возвращает. # Callable[[int, int], int] — функция, которая принимает два int и возвращает int def apply_op(a: int, b: int, op: Callable[[int, int], int]) -> int: # [int, int] - список аргументов функции # , int - тип возвращаемого значения функции return op(a, b) # Обычная функция, подходящая под Callable[[int, int], int] def add(x: int, y: int) -> int: return x + y # Передаём функцию как аргумент result: int = apply_op(2, 3, add) print(result) # 5 Преобразование типов -------------------- В Python есть несколько полезных встроенных функций, которые позволяют преобразовать данные из одного типа в другой. Конвертация строки в двоичную, десятичную, шестнадцатеричную систему. .. code:: python # Преобразует строку как двоичное число в десятичное: int("11111111", 2) # 255 С помощью функции int можно преобразовать и число в двоичной записи в десятичную (двоичная запись должна быть в виде строки) # Преобразовать десятичное число в двоичный формат можно с помощью: bin(10) #'0b1010' # Преобразовать десятичное число в шестнадцатеричный формат: hex(10) #'0xa' Преобразование типов .. code:: python # Преобразует в список: list("string") #['s', 't', 'r', 'i', 'n', 'g'] list({1,2,3}) #[1, 2, 3] list((1,2,3,4)) #[1, 2, 3, 4 # Преобразует в множество: set([1,2,3,3,4,4,4,4]) #{1, 2, 3, 4} set((1,2,3,3,4,4,4,4)) #{1, 2, 3, 4} set("string string") #{' ', 'g', 'i', 'n', 'r', 's', 't'} # Преобразует в кортеж: tuple([1,2,3,4]) #(1, 2, 3, 4) tuple({1,2,3,4}) #(1, 2, 3, 4) tuple("string") #('s', 't', 'r', 'i', 'n', 'g') # Преобразует число в строку: str(10) #'10' # Преобразует строку в цифру: int("10") #10 # Преобразует в число с плавающей точкой: a = float("3.14") # строка '3.14' преобразуется в число 3.14 b = float(10) # целое число 10 преобразуется в 10.0 Проверка типов -------------- .. code:: python # Проверяет, сосоит ли строка из одних только цифр "a".isdigit() #False "a10".isdigit() #False "10".isdigit() #True # Проверяет, состоит ли строка из одних букв: "a".isalpha() #True "a100".isalpha() #False "a-- ".isalpha() #False "a ".isalpha() #False # Позволяет проверить, состоит ли строка из букв или цифр: "a".isalnum() #True "a10".isalnum() #True **type()** Иногда, в зависимости от результата, библиотека или функция может выводить разные типы объектов. Например, если объект один, возвращается строка, если несколько, то возвращается кортеж. Нам же надо построить ход программы по-разному, в зависимости от того, была ли возвращена строка или кортеж. .. code:: python type("string") #str type("string") is str #True #Аналогично с кортежем (и другими типами данных): type((1,2,3)) #tuple type((1,2,3)) is tuple #True type((1,2,3)) is list #False Файлы ----- Файлы — это основной способ хранения данных на компьютере. В Python объекты файлов предоставляют интерфейс для чтения и записи данных: текстов, документов, аудио, JSON, CSV и т. д. Работа с файлами включает открытие, чтение/запись и закрытие файлов, а также управление путями и обработку ошибок. Используйте конструкцию with open(...) as f: для автоматического закрытия файлов. Закрывайте файлы после ручного открытия с open(). Используйте абсолютные пути, если файл всегда в одном месте, и относительные, если код должен работать независимо от структуры каталогов. Для больших файлов лучше читать построчно (for line in file) или с использованием readline(), чтобы не загружать весь файл в память. Для создания и удаления папок применяйте Path.mkdir() и Path.rmdir() (или shutil.rmtree() для непустых). 1. Создание и открытие файлов Для создания объекта файла используется встроенная функция open(): .. code:: python f = open('data.txt', 'w') # Создать новый файл в режиме записи ('w') f.write('Hello\n') # Записать строку в файл f.write('world\n') # Еще одна строка f.close() # Закрыть файл и сбросить буфер на диск Основные режимы: 'w' — режим записи (write). Создает файл, если его нет, или очищает существующий. 'r' — режим чтения (read), используется по умолчанию. 'a' — режим дозаписи (append), добавляет данные в конец файла. Дополнительные режимы: 'x' — создает новый файл и открывает его для записи. Если файл существует, будет ошибка. Бинарные и текстовые режимы: 'b' — бинарный режим (для чтения/записи байтов). 't' — текстовый режим (по умолчанию). Комбинации: 'r+' – открыть для чтения и записи (ошибка, если файл не существует). 'w+' – открыть для чтения и записи, но предварительно очищает файл или создает новый. 'a+' – открыть для чтения и дозаписи (добавляет данные в конец файла, если файл есть; если нет — создается новый). 'x+' – создать новый файл и открыть для чтения и записи (ошибка, если файл уже есть). 1. Чтение файлов Полное чтение .. code:: python f = open('data.txt', 'r') # Открытие файла для чтения text = f.read() # Прочитать все содержимое в строку f.close() print(text) Чтение построчно .. code:: python with open('data.txt', 'r') as f: # Автоматическое открытие и закрытие файла for line in f: print(line, end='') # end='' убирает двойной перенос Чтение с помощью readlines() и readline() .. code:: python with open('data.txt', 'r') as f: lines = f.readlines() # Список строк файла print(lines) line = f.readline() # Считывает одну строку Чтение полностью до пустой строки. .. code:: python with open('test/test.txt') as f: while True: line = f.readline() print(line) if not line: break 1. Запись в файлы .. code:: python with open('data.txt', 'w', encoding='utf-8') as f: # 'w' перезаписывает файл f.write("Первая строка\n") # 'a' добавляет строки в конец файла. f.write("Вторая строка\n") # encoding='utf-8' обеспечивает корректное сохранение текста на русском и других языках. 4. Обработка текста перед записью/анализом .. code:: python with open('data.txt', encoding='utf-8') as f: text = f.read() text = text.replace("\n", " ") # заменяем переносы на пробелы text = text.replace(",", "").replace(".", "") # убираем пунктуацию text = text.lower() # переводим в нижний регистр words = text.split() # создаем список слов words.sort() # сортируем слова 5. Работа с путями к файлам Функциональный подход (модуль os.path) .. code:: python from os import path print(path.abspath('.')) # Абсолютный путь к текущей папке print(path.exists('data.txt')) # Проверка существования файла print(path.('C:/local/bin').exists()) # Проверка наличия папки # Абсолютный путь жестко привязан к конкретной системе: C:/Users/Vasya/Documents/file.txt. # Относительный путь указывает путь относительно текущей рабочей папки: data/file.txt. # В относительных путях используется специальный элемент (работае так же и в Path ): # . — текущая папка # .. — на одну папку вверх # ../.. — на две папки вверх # ../../.. — на три папки вверх Объектно-ориентированный подход (модуль pathlib) .. code:: python from pathlib import Path file_path = Path('test.txt') # Файл в текущей папке print(file_path.exists()) # Проверка существования print(file_path.is_file()) # Проверка, является ли файлом print(file_path.is_dir()) # Проверка, является ли папкой print(file_path.absolute()) # Абсолютный путь # Примеры операций с Path: cwd = Path('.') # текущая папка for f in cwd.iterdir(): # список файлов и папок print(f) new_folder = Path('example') if not new_folder.exists(): new_folder.mkdir() # создание папки new_folder.rmdir() # удаление папки (если пустая) # Для удаления папки с содержимым используйте shutil.rmtree(). # Объектно-ориентированный подход удобен для построения и объединения путей: # Path('C:/') / 'local' / 'bin' # 'C:/local/bin' # Создание папки cwd = Path('C:/Users') / 'ERRoR79' / 'Desktop' / 'krutaten' # Путь к папке if not cwd.exists(): # проверка если папка отсутствует cwd.mkdir() # создание папки if cwd.exists(): # если папка есть cwd.rmdir() # удаление папки # import shutil # shutil.rmtree(cwl) # Удаление папки если в ней есть файлы cwd = Path('failes') cmd.mkdir(exist_ok=True) # если такая папка есть то ошибки не будет Path — не файл и не папка, а объект, который описывает путь. 1. Методы работы с путями Позволяют создавать и преобразовывать пути: absolute() — абсолютный путь resolve() — абсолютный путь с разрешением .. и симлинков joinpath() — соединение путей / — оператор, альтернатива joinpath parent, parents — родительские директории parts — путь как кортеж частей 2. Проверки типа объекта Определяют, что это за путь: exists() — существует ли путь is_file() — это файл is_dir() — это папка is_absolute() — абсолютный путь is_symlink() — символическая ссылка 3. Навигация и поиск Работа с содержимым каталогов: iterdir() — перебор файлов и папок glob() — поиск по шаблону rglob() — рекурсивный поиск 4. Работа с файлами Чтение и запись без open(): read_text() / write_text() read_bytes() / write_bytes() open() — открыть файл 5. Управление файлами и папками Операции с файловой системой: mkdir() — создать папку rmdir() — удалить пустую папку unlink() — удалить файл rename() / replace() — переименование touch() — создать пустой файл 6. Информация о пути Свойства и метаданные: name — имя файла stem — имя без расширения suffix / suffixes — расширение(я) root, drive, anchor — части пути stat() — информация из ОС 1. Удаление файлов .. code:: python from pathlib import Path file = Path('test_file.txt') # Создаёт объект Path, представляющий путь # к файлу 'test_file.txt' в текущей рабочей директории # (файл может как существовать, так и отсутствовать) if file.exists(): # проверка наличие файла file.unlink() # удаление файла 7. JSON и другие форматы .. code:: python import json from pathlib import Path DATA_FILE = 'data.json' # Загрузка данных def load(): # Функция загрузки данных из файла DATA_FILE if not Path(DATA_FILE).exists(): # Проверяем, существует ли файл по указанному пути return {} # Если файла нет, возвращаем пустой словарь, чтобы избежать ошибки открытия with open(DATA_FILE, 'r', encoding='utf-8') as f: # Открываем файл в режиме чтения с кодировкой UTF-8 return json.load(f) # Читаем содержимое файла и преобразуем JSON в объект Python (обычно dict) # Сохранение данных в файл DATA_FILE def save(data): # Функция принимает объект Python (обычно словарь или список) для сохранения with open(DATA_FILE, 'w', encoding='utf-8') as f: # Открываем файл в режиме записи; если файл существует — он будет перезаписан json.dump( # Сериализуем объект Python в формат JSON data, # Данные, которые нужно сохранить f, # Файловый объект, в который производится запись ensure_ascii=False, # Разрешает сохранение русских и других не-ASCII символов indent=2 # Делает JSON человекочитаемым за счёт отступов ) Операторы языка Python ---------------------- Большинство предложений (логических строк) в программах содержат выражения. Простой пример выражения: 2 + 3. Выражение можно разделить на операторы и операнды. Операторы – это некий функционал, производящий какие-либо действия, который может быть представлен в виде символов, как например +, или специальных зарезервированных слов. Операторы могут производить некоторые действия над данными, и эти данные называются операндами. В нашем случае 2 и 3 – это операнды. Базовые операторы ^^^^^^^^^^^^^^^^^ +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | Оператор | Название | Объяснение | Примеры | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | '+' | Сложение | Суммирует два объекта | 3 + 5 даст 8; 'a' + 'b' даст 'ab' | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | '-' | Вычитание | Даёт разность двух чисел; если первый операнд | | | | | отсутствует, он считается равным нулю | -5.2 даст отрицательное число, а 50 - 24 даст 26. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | '*' | Умножение | Даёт произведение двух чисел или возвращает | | | | | строку, повторённую заданное число раз. | 2 * 3 даст 6. 'la' * 3 даст 'lalala'. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | '**' | Возведение в степень | Возвращает число х, возведённое в степень y | 3** 4 даст 81 (т.е. 3 * 3 * 3 * 3) | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | / | Деление | Возвращает частное от деления x на y | 4 / 3 даст 1.3333333333333333. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | // | Целочисленное деление | Возвращает неполное частное от деления | 4 // 3 даст 1. -4 // 3 даст -2. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | % | Деление по модулю | Возвращает остаток от деления | 8 % 3 даст 2. -25.5 % 2.25 даст 1.5. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | << | Сдвиг влево | Сдвигает биты числа влево на заданное | 2 << 2 даст 8. В двоичном виде 2 представляет собой 10. | | | | количество позиций. (Любое число в памяти | Сдвиг влево на 2 бита даёт 1000, что в десятичном виде означает 8. | | | | компьютера представлено в виде битов - или | | | | | двоичных чисел, т.е. 0 и 1) | | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | >> | Сдвиг вправо | Сдвигает биты числа вправо на заданное | 11 >> 1 даст 5. В двоичном виде 11 представляется как 1011, | | | | число позиций. | что будучи смещённым на 1 бит вправо, даёт 101, а это, в свою | | | | | очередь, не что иное как десятичное 5 | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | & | Побитовое И | Побитовая операция И над числами | 5 & 3 даёт 1. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | '|' | Побитовое ИЛИ | Побитовая операция ИЛИ над числами | 5 | 3 даёт 7 | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | ^ | Побитовое ИСКЛЮЧИТЕЛЬНО ИЛИ | Побитовая операция ИСКЛЮЧИТЕЛЬНО ИЛИ | 5 ^ 3 даёт 6 | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | ~ | Побитовое НЕ | Побитовая операция НЕ для числа x | | | | | соответствует -(x+1) | ~5 даёт -6. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | < | Меньше | Определяет, верно ли, что x меньше y. | | | | | Все операторы сравнения возвращают | 5 < 3 даст False, | | | | True или False [1]. Обратите внимание на | а 3 < 5 даст True. | | | | заглавные буквы в этих словах. | Можно составлять произвольные цепочки сравнений: 3 < 5 < 7 даёт True. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | > | Больше | Определяет, верно ли, что x больше y | 5 > 3 даёт True. Если оба операнда - числа, то перед сравнением | | | | | они оба преобразуются к одинаковому типу. В противном случае всегда | | | | | возвращается False. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | <= | Меньше или равно | Определяет, верно ли, что x меньше или равно y | x = 3; y = 6; x <= y даёт True. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | >= | Больше или равно | Определяет, верно ли, что x больше или равно y | x = 4; y = 3; x >= 3 даёт True. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | == | Равно | Проверяет, одинаковы ли объекты | x = 2; y = 2; x == y даёт True. x = 'str'; y = 'stR'; | | | | | x == y даёт False. x = 'str'; y = 'str'; x == y даёт True. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | != | Не равно | Проверяет, верно ли, что объекты не равны | x = 2; y = 3; x != y даёт True. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | not | Логическое НЕ | Если x равно True, оператор вернёт False. | | | | | Если же x равно False, получим True. | x = True; not x даёт False. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | and | Логическое И | x and y даёт False, если x равно False , | x = False; y = True; x and y возвращает False, поскольку x равно | | | | в противном случае возвращает значение y | False. В этом случае Python не станет проверять значение y, | | | | | так как уже знает, что левая часть выражения 'and' равняется False, | | | | | что подразумевает, что и всё выражение в целом будет равно False, | | | | | независимо от значений всех остальных операндов. Это называется | | | | | укороченной оценкой булевых (логических) выражений. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | or | Логическое ИЛИ | Если x равно True, в результате получим True, | x = True; y = False; x or y даёт True. | | | | в противном случае получим значение y | Здесь также может производиться укороченная оценка выражений. | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | := | Присваивает значение | Присваивает значение переменной в выражении | if (n := len(mylist)) > 5: | | | | (оператор присвоения внутри выражения). | | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | is | Сравнение идентичности | | a is b | | | (один объект в памяти) | | | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | is not | Не идентичны | | a is not b | | | | | | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | in | Проверка, содержится ли | | x in list | | | элемент | | | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ | not in | Проверка отсутствия элемента | | x not in list | | | | | | +----------+--------------------------------+-------------------------------------------------+------------------------------------------------------------------------+ Управляющие операторы ^^^^^^^^^^^^^^^^^^^^^ Условные операторы (if/else) """""""""""""""""""""""""""" Оператор if используется для проверки условий: если условие верно, выполняется блок выражений (называемый “if-блок”), иначе выполняется другой блок выражений (называемый “else-блок”). Блок “else” является необязательным. .. warning:: В языке Python блоки разедяются табами(4 пробела) или пробелами Запомните эмпирическое правило: хотя вы можете использовать для отступов пробелы или табуляции (4 пробела), их смешивание внутри блока обычно не будет удачной иде­ей применяйте либо то, либо другое. Формально табуляция считается достаточным количеством пробелов, чтобы сместить текущую строку на расстояние, кратное 8, и код будет работать в случае согласованного смешивания табуляций и пробелов. Тем не менее, такой код может быть сложнее изменять. Хуже того, смешивание табуляций и пробелов затрудняет чтение кода целиком, не говоря уже о правилах синтаксиса Python — табуляции в редакторе сменившего вас программиста могут выглядеть сов­ сем не так, как в вашем редакторе. Пример использования оператора if .. code:: python number = 23 guess = int(input('Введите целое число : ')) if guess == number: print('Поздравляю, вы угадали,') # Здесь начинается новый блок print('(хотя и не выиграли никакого приза!)') # Здесь заканчивается новый блок elif guess < number: print('Нет, загаданное число немного больше этого.') # Ещё один блок # Внутри блока вы можете выполнять всё, что угодно ... else: print('Нет, загаданное число немного меньше этого.') # чтобы попасть сюда, guess должно быть больше, чем number print('Завершено') # Это последнее выражение выполняется всегда после выполнения оператора if # Выполняет все сравнения if guess == number print(1) if guess < number print(2) if guess > number print(3) Выражения: .. code:: python # Проверка наличия значения или ключа if not per.get('name'): # True, если ключ 'name' отсутствует или значение пустое if name: # True, если переменная непустая (не None, не '', не 0 и т.д.) # Сравнения if name > 1: # True, если значение больше 1 if name and name > 1: # True, если оба условия истинны (логическое И) # Проверка типа if isinstance(a, (int, float)): # True, если a принадлежит хотя бы одному типу из кортежа if type(my) is int: # True, если тип переменной точно int # Специальные случаи if 0: # False if 1: # True # Проверка исключений типов if isinstance(i, tip) and not (tip == int and isinstance(i, bool)): # True, если i принадлежит типу tip, кроме случая, когда tip=int, а i bool # Логические операторы a and b (если одно из выражений ложное) a or b (если оба выражения ложных) Тернарный оператор (условное выражение) Используется для выбора значения или функции на месте. Подходит, когда есть одно условие, и нужно сразу что-то выполнить или вернуть. .. code:: python n = 5 print('ff') if type(n) is int else print('dd') # Проверяет тип переменной n # Если n — int, выведет 'ff', иначе 'dd' result = "Число положительное" if n > 0 else "Число неположительное" print(result) # Позволяет записать условие и действия в одну строку вместо полноценного if-else блока. # Часто используют для краткой и наглядной логики присваивания или вывода. img = 4 def fr(): print('good') def tg(): print('not') ret = fr() if True else tg() # Если условие True → вызывается fr(), иначе tg() Сопоставление с образцом (match-case) """"""""""""""""""""""""""""""""""""" Когда применять: Много if-elif-else Работа со структурированными данными (списки, словари, объекты) Чтобы сделать код чище и читаемее Примеры использования: CLI, меню, команды бота, Парсинг JSON/API, Обработка HTTP-статусов .. code:: python fruit = "Банан" match fruit: # проверяемая переменная case "apple": # если "apple" print("Яблоко") case "banana": # если "banana" print("Банан") case _: # любой другой вариант print("Неизвестный фрукт") case "apple" | "banana": # несколько вариантов pass case ["user", name]: # проверка структуры списка/кортежа pass case x if x < 10: # условие внутри case pass case User(name="Alice"): # сопоставление с классом pass Оператор while """""""""""""" Оператор while — самая универсальная конструкция для итераций в языке Python. Выражаясь простыми терминами, он многократно выполняет блок операторов (обыч­ но с отступом) до тех пор, пока проверка в заголовочной части оценивается как истин­ ное значение. Это называется “циклом”, потому что управление продолжает возвра­ щаться к началу оператора, пока проверка не даст ложное значение. Когда результат проверки становится ложным, управление переходит на оператор, следующий после блока while. Совокупный эффект в том, что тело цикла выполняется многократно, пока проверка в заголовочной части дает истинное значение. Если проверка оцени­ вается в ложное значение с самого начала, тогда тело цикла никогда не выполнится и оператор while пропускается. В своей самой сложной форме оператор while состоит из строки заголовка с вы­ ражением проверки, тела с одним или большим количеством оператором с отступами и необязательной части else, которая выполняется, если управление покидает цикл, а оператор break не встретился. Python продолжает оценивать выражение проверки в строке заголовка и выполняет операторы, вложенные в тело цикла, пока проверка не возвратит ложное значение: .. code:: python number = 23 running = True while running: guess = int(input('Введите целое число : ')) if guess == number: print('Поздравляю, вы угадали.') running = False # это останавливает цикл while elif guess < number: print('Нет, загаданное число немного больше этого.') else: print('Нет, загаданное число немного меньше этого.') else: print('Цикл while закончен.') # Здесь можете выполнить всё что вам ещё нужно print('Завершение.') Цикл for """""""" Циклы перебирают последовательности: diсt, set, list, str, range, tuple Оператор осуществляет итерацию по последовательности объектов, последовательность – это упорядоченный набор элементов. .. code:: python for х in ["spam", "eggs", "ham"]: print(x, end=' ') # spam # eggs # ham # end=' ' меняет поведение print: по умолчанию print() ставит перенос строки \n, # но тут вместо него ставится пробел. Поэтому все значения выводятся в одну строку через пробел: .. code:: python for i in range(1, 5): print(i) else: print('Цикл for закончен') Вложенные циклы for ~~~~~~~~~~~~~~~~~~~ Давайте теперь взглянем на цикл for, который сложнее тех, что мы видели до сих пор. В приведенном ниже примере иллюстрируется вложение операторов и конструк­ ция else цикла for. Имея список объектов (items) и список ключей (tests), код ищет каждый ключ в списке объектов и сообщает о результате поиска: .. code:: python items = ["ааа", 111, (4, 5), 2.01] tests = [(4, 5) , 3.14] for key in tests: for item in items: if item - key: print (key, "was found") break else: print(key, "not found!") Оператор break """""""""""""" Оператор break служит для прерывания[7] цикла, т.е. остановки выполнения команд даже если условие выполнения цикла ещё не приняло значения False или последовательность элементов не закончилась. Важно отметить, что если циклы for или while прервать оператором break, соответствующие им блоки else выполняться не будут. .. code:: python # Бесконечный цикл while True: # Неизменяемое условие print('1') while True: s = input('Введите что-нибудь : ') if s == 'выход': break # Выход из цикла print('Длина строки:', len(s)) print('Завершение') Оператор continue """"""""""""""""" Оператор continue используется для указания Python, что необходимо пропустить все оставшиеся команды в текущем блоке цикла и продолжить[9] со следующей итерации цикла. .. code:: python # Прерывание с помощью ввода while True: s = input('Введите что-нибудь : ') if s == 'выход': break # Выход из цикла if len(s) < 3: print('Слишком мало') continue # Пропуск операции print('Введённая строка достаточной длины') # Разные другие действия здесь... Ну и в качестве маленького примера давайте нарисуем в консоли Ёлочку :) .. literalinclude:: ../../Examples/herringbone.py :language: python Цикл по словарю (через items()) .. code:: python l = {'1': 'зн1', '2': 'зн2', '3': 'зн3'} for item in l.items(): # items() - возвращает последовательность кортеж ключ, пара key, value = item # распаковывает кортеж в две переменные: print(key, value) # Сразу распаковка в цикле for key, value in l.items(): # items() - возвращает последовательность кортежа ключ, пара print(key, value) Генераторы Преимущество генераторов, в малом объеме памяти у объекта .. code:: python # Список — генератор списка absol = [3, 4, 7, -2, 6, -1] # список чисел. absol_1 = [abs(num) for num in absol if num % 2 == 0] # for num in absol — перебрать каждый элемент # if num % 2 == 0 — оставить только чётные числа # abs(num) — взять модуль числа (убрать минус) print(absol_1) # Генератор множества (set comprehension) myset = [3, 4, 7, -2, 6, -1] new_myset = {val * val for val in myset} # Перебираем каждый элемент val, Возводим его в квадрат val * val, Результаты собираются в {...} — это множество print(new_myset) # не хранит дубликаты, не гарантирует порядок # Генератор словаря (dict comprehension) my_dict = {'1': 10, 'res': 7, 'wed': 14} new_tunec = {key: value * 10 for key, value in my_dict.items()} # my_dict.items() даёт пары (ключ, значение) print(new_tunec) # print(new_myset) # at 0x000001BDA7046180> print(type(new_myset)) # Функции языка Python -------------------- Функции – это многократно используемые фрагменты программы. Они позволяют дать имя определённому блоку команд с тем, чтобы впоследствии запускать этот блок по указанному имени в любом месте программы и сколь угодно много раз. Это называется вызовом функции. Принципы написания функций Одна функция — одна задача: Функция должна делать только одно логически завершённое действие. Если внутри появляются слова «и», «или», «а ещё» — скорее всего, функцию стоит разбить. Название функции начинается с глагола Имя должно описывать действие. Название отражает суть задачи По имени должно быть понятно: что делает функция без просмотра её реализации Функции не должны изменять внешние объекты (без необходимости) Желательно, чтобы функция: не меняла глобальные переменные не изменяла переданные объекты напрямую возвращала результат, а не имела побочные эффекты .. code:: python def sayHello(): # def - определение функции, sayHello - имя функции print('Привет, Мир!') # блок, принадлежащий функции # Конец функции sayHello() # вызов функции sayHello() # ещё один вызов функции Параметры функций ^^^^^^^^^^^^^^^^^ Функции могут принимать параметры(значения), передаваемые функции для того, чтобы она что-либо сделала с ними. Эти параметры похожи на переменные, за исключением того, что значение этих переменных указывается при вызове функции, и во время работы функции им уже присвоены их значения. Параметры указываются в скобках при объявлении функции и разделяются запятыми. Аналогично мы передаём значения, когда вызываем функцию. Обратите внимание на терминологию: имена, указанные в объявлении функции, называются параметрами, тогда как значения, которые вы передаёте в функцию при её вызове, – аргументами. .. code:: python def printMax(a, b): # a, b - параметры функции if a > b: print(a, 'максимально') elif a == b: print(a, 'равно', b) else: print(b, 'максимально') # прямая передача значений printMax(3, 4) # 3, 4 - аргументы функции # передача переменных в качестве аргументов x = 5 y = 7 printMax(x, y) Локальные переменные ^^^^^^^^^^^^^^^^^^^^ При объявлении переменных внутри определения функции, они никоим образом не связаны с другими переменными с таким же именем за пределами функции – т.е. имена переменных являются локальными в функции. Это называется областью видимости переменной. Область видимости всех переменных ограничена блоком, в котором они объявлены, начиная с точки объявления имени. .. code:: python x= 50 def func(x): print('x равен', x) x = 2 print('Замена локального x на', x) func(x) print('x по-прежнему', x) Зарезервированное слово “global” ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Чтобы присвоить некоторое значение переменной, определённой на высшем уровне программы (т.е. не в какой-либо области видимости, как то функции или классы), необходимо указать Python, что её имя не локально, а глобально (global). Сделаем это при помощи зарезервированного слова global. Без применения зарезервированного слова global невозможно присвоить значение переменной, определённой за пределами функции. Можно использовать уже существующие значения переменных, определённых за пределами функции (при условии, что внутри функции не было объявлено переменной с таким же именем). Однако, это не приветствуется, и его следует избегать, поскольку человеку, читающему текст программы, будет непонятно, где находится объявление переменной. Использование зарезервированного слова global достаточно ясно показывает, что переменная объявлена в самом внешнем блоке. .. code:: python x = 50 def func(): global x print('x равно', x) x = 2 print('Заменяем глобальное значение x на', x) func() print('Значение x составляет', x) Зарезервированное слово “nonlocal” ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Мы увидели, как получать доступ к переменным в локальной и глобальной области видимости. Есть ещё один тип области видимости, называемый “нелокальной” (nonlocal) областью видимости, который представляет собой нечто среднее между первыми двумя. Нелокальные области видимости встречаются, когда вы определяете функции внутри функций. Поскольку в Python всё является выполнимым кодом, вы можете определять функции где угодно. .. code:: python def func_outer(): x = 2 print('x равно', x) def func_inner(): nonlocal x x = 5 func_inner() print('Локальное x сменилось на', x) func_outer() Значения аргументов по умолчанию ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Зачастую часть параметров функций могут быть необязательными, и для них будут использоваться некоторые заданные значения по умолчанию, если пользователь не укажет собственных. Этого можно достичь с помощью значений аргументов по умолчанию. Их можно указать, добавив к имени параметра в определении функции оператор присваивания (=) с последующим значением. Обратите внимание, что значение по умолчанию должно быть константой. Или точнее говоря, оно должно быть неизменным[1] – это объясняется подробнее в последующих главах. А пока запомните это. .. code:: python def say(message, times = 1): print(message * times) say('Привет') say('Мир', 5) .. warning:: Важно Значениями по умолчанию могут быть снабжены только параметры, находящиеся в конце списка параметров. Таким образом, в списке параметров функции параметр со значением по умолчанию не может предшествовать параметру без значения по умолчанию. Это связано с тем, что значения присваиваются параметрам в соответствии с их положением. Например, def func(a, b=5) допустимо, а def func(a=5, b) – не допустимо. Ключевые аргументы ^^^^^^^^^^^^^^^^^^ Если имеется некоторая функция с большим числом параметров, и при её вызове требуется указать только некоторые из них, значения этих параметров могут задаваться по их имени – это называется ключевые параметры. В этом случае для передачи аргументов функции используется имя (ключ) вместо позиции (как было до сих пор). Есть два преимущества такого подхода: во-первых, использование функции становится легче, поскольку нет необходимости отслеживать порядок аргументов; во-вторых, можно задавать значения только некоторым избранным аргументам, при условии, что остальные параметры имеют значения аргумента по умолчанию. .. code:: python def func(a, b=5, c=10): print('a равно', a, ', b равно', b, ', а c равно', c) func(3, 7) func(25, c=24) func(c=50, a=100) Переменное число параметров ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Иногда бывает нужно определить функцию, способную принимать любое число параметров. Этого можно достичь при помощи звёздочек (сохраните как function_varargs.py): .. code:: python def total(a=5, *numbers, **phonebook): print('a', a) #проход по всем элементам кортежа for single_item in numbers: print('single_item', single_item) #проход по всем элементам словаря for first_part, second_part in phonebook.items(): print(first_part,second_part) print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560)) Только ключевые параметры ^^^^^^^^^^^^^^^^^^^^^^^^^ Если некоторые ключевые параметры должны быть доступны только по ключу, а не как позиционные аргументы, их можно объявить после параметра со звёздочкой (сохраните как keyword_only.py): .. code:: python def total(initial=5, *numbers, extra_number): count = initial for number in numbers: count += number count += extra_number print(count) total(10, 1, 2, 3, extra_number=50) total(10, 1, 2, 3) # Вызовет ошибку, поскольку мы не указали значение # аргумента по умолчанию для 'extra_number'. Оператор “return” ^^^^^^^^^^^^^^^^^ Оператор return используется для возврата из функции, т.е. для прекращения её работы и выхода из неё. При этом можно также вернуть некоторое значение из функции. .. code:: python # Просто выводит на экран def print(str): print("Выведит текст в консоль") # return возвращает значение для дальнейшего использования def add(a, b): return a + b # Возвращает результат выражения result = add(3, 5) print(result) # 8 тут может быть любой код. # return - возвращает значение в зависимости от условия def maximum(x, y): if x > y: return x elif x == y: return 'Числа равны.' else: return y print(maximum(2, 3)) return - заавершает действие фунции Стандартные Функции: ^^^^^^^^^^^^^^^^^^^^ 1. Функции ввода / вывода print() — вывод данных Используется для: вывода информации пользователю отладки .. code:: python print("Hello, world") print(10, 20, 30) input() — ввод строки от пользователя Используется для: получения данных с клавиатуры интерактивных программ .. code:: python name = input("Введите имя: ") print(name) 2. Работа с типами и преобразования Используется, когда: ввод получен строкой дробная часть не нужна работа с индексами, счётчиками int() - Преобразование строки или числа в целое число. Используется, когда: ввод получен строкой дробная часть не нужна работа с индексами, счётчиками .. code:: python x = int("123") # строка → int y = int(3.9) # float → int (отбрасывает дробную часть) float() - Преобразование в вещественное число (с плавающей точкой). Используется, когда: нужны дробные значения расчёты, измерения, проценты .. code:: python x = float("3.14") # строка → float y = float(10) # int → float complex() - Работа с комплексными числами (математика, физика, сигналы). Используется, когда: математика физика обработка сигналов .. code:: python z = complex(2, 3) # 2 + 3j # z.real → 2.0 # z.imag → 3.0 str() - Преобразование данных в строку (вывод, логирование, JSON). Используется, когда: нужно вывести данные логирование сериализация (JSON, файлы) .. code:: python s = str(100) # int → str t = str(3.14) # float → str bool() - Логические проверки (if, while). Используется, когда: условия в if / while проверки наличия данных .. code:: python bool(0) # False bool(1) # True bool("") # False bool("text") # True bytes() - Работа с сырыми бинарными данными (файлы, сеть, шифрование). Используется, когда: работа с файлами сеть шифрование данные «как есть», без изменения .. code:: python b = bytes("hi", "utf-8") # строка → bytes # b'hi' bytearray() - Изменяемые бинарные данные (буферы, протоколы). Используется, когда: нужно менять байты буферы сетевые протоколы .. code:: python ba = bytearray(b"abc") # bytes → bytearray ba[0] = 100 # изменяем байт # bytearray(b'dbc') memoryview() - Работа с большими данными без копирования (производительность). Используется, когда: большие данные важна производительность нельзя копировать массивы .. code:: python data = bytearray(b"abcd") mv = memoryview(data) # представление в памяти mv[1] = 120 # меняет исходные данные # bytearray(b'axcd') 1. Коллекции и структуры данных list() — список Используется, когда: порядок важен элементы нужно менять допускаются дубликаты .. code:: python lst = list([1, 2, 3]) # создание списка lst.append(4) # добавление элемента lst[0] = 10 # изменение элемента print(lst) # [10, 2, 3, 4] tuple() — кортеж Используется, когда: данные не должны изменяться нужен фиксированный набор значений можно использовать как ключ словаря .. code:: python tpl = tuple([1, 2, 3]) # создание кортежа print(tpl[0]) # доступ по индексу # tpl[0] = 10 ошибка (неизменяем) set() — множество Используется, когда: важна уникальность не важен порядок нужны операции: объединение, пересечение .. code:: python s = set([1, 2, 2, 3]) # дубликаты удаляются s.add(4) # добавление элемента print(s) # {1, 2, 3, 4} frozenset() — неизменяемое множество Используется, когда: нужно множество как ключ словаря требуется гарантия неизменности .. code:: python fs = frozenset([1, 2, 3]) # fs.add(4) ошибка print(fs) dict() — словарь Используется, когда: нужен быстрый доступ по ключу данные имеют структуру «имя → значение» .. code:: python d = dict(one=1, two=2) # создание словаря d["three"] = 3 # добавление пары print(d["one"]) # 1 range() — диапазон чисел Используется, когда: нужен диапазон чисел важна производительность и память часто применяется в циклах .. code:: python r = range(1, 5) # 1, 2, 3, 4 print(list(r)) # [1, 2, 3, 4] r2 = range(0, 10, 2) # шаг 2 print(list(r2)) # [0, 2, 4, 6, 8] 4. Математика и числа abs() — модуль числа, Возвращает абсолютное значение (без знака). Используется, когда: нужна величина без знака расчёт расстояний сравнение отклонений .. code:: python abs(-10) # 10 abs(3.5) # 3.5 round() — Округляет число до заданного количества знаков. Используется, когда: вывод чисел пользователю финансовые расчёты форматирование результатов .. code:: python round(3.14159, 2) # 3.14 round(2.5) # 2 (банковское округление) pow() — возведение в степень Используется, когда: математические вычисления алгоритмы нужна поддержка 3 аргументов (модуль) .. code:: python pow(2, 3) # 8 pow(2, 3, 5) # 3 → (2³) % 5 divmod() — частное и остаток Используется, когда: нужно одновременно получить деление и остаток работа с разрядами, временем, координатами .. code:: python divmod(17, 5) # (3, 2) sum() — сумма Используется, когда: подсчёт итогов агрегация данных работа с числами .. code:: python sum([1, 2, 3, 4]) # 10 sum([1, 2, 3], 10) # 16 (начальное значение) min(), max() — минимум и максимум Используются, когда: поиск предельных значений ограничения анализ данных .. code:: python min(3, 1, 5) # 1 max([3, 1, 5]) # 5 min("apple", "banana") # 'apple' (лексикографически) 5. Проверки и сравнения len() — длина Используется, когда: нужно узнать размер коллекции проверка на пустоту контроль границ .. code:: python len("hello") # 5 len([1, 2, 3]) # 3 len({1, 2, 3}) # 3 type() — тип объекта Используется, когда: отладка изучение объектов интроспекция .. code:: python type(10) # type("abc") # isinstance() — проверка типа Используется, когда: безопасная проверка типов поддержка наследования .. code:: python isinstance(10, int) # True isinstance("hi", (str, bytes)) # True issubclass() — проверка наследования Используется, когда: работа с иерархией классов проверка интерфейсов .. code:: python class A: pass class B(A): pass issubclass(B, A) # True issubclass(A, B) # False id() — идентификатор объекта Используется, когда: отладка понимание ссылок проверка, один ли это объект .. code:: python a = [1, 2] b = a id(a) == id(b) # True hash() — хеш-значение Используется, когда: объект используется как ключ словаря работа с set сравнение неизменяемых объектов .. code:: python hash("hello") hash(10) # hash([1, 2, 3]) ошибка (изменяемый тип) 6. Логика и булевы операции all() — Возвращает True, если все элементы в итерируемом объекте истинны Используется, когда: нужно проверить выполнение всех условий валидация данных .. code:: python all([True, True, True]) # True all([True, False, True]) # False all([1, 2, 3]) # True all([1, 0, 3]) # False all([]) # True (пустой набор) any() — хотя бы один истинный Используется, когда: достаточно выполнения одного условия поиск совпадений проверки флагов .. code:: python any([False, False, True]) # True any([False, False, False]) # False any([0, "", None, 5]) # True any([]) # False (пустой набор) 7. Работа с последовательностями sorted() — сортировка Используется, когда: нужен отсортированный результат исходные данные нельзя менять требуется сортировка по ключу .. code:: python sorted([3, 1, 2]) # [1, 2, 3] sorted("cba") # ['a', 'b', 'c'] sorted([("a", 3), ("b", 1)], key=lambda x: x[1]) # [('b', 1), ('a', 3)] reversed() — обратный порядок Используется, когда: нужно пройти коллекцию с конца не хочется создавать копию списка .. code:: python list(reversed([1, 2, 3])) # [3, 2, 1] list(reversed("abc")) # ['c', 'b', 'a'] enumerate() — индекс + значение Используется, когда: нужен индекс в цикле нумерация элементов .. code:: python for i, val in enumerate(["a", "b", "c"]): print(i, val) # 0 a # 1 b # 2 c zip() — объединение последовательностей Используется, когда: нужно обрабатывать данные параллельно склеивание структур данных .. code:: python a = [1, 2, 3] b = ["a", "b", "c"] list(zip(a, b)) # [(1, 'a'), (2, 'b'), (3, 'c')] map() — применение функции Используется, когда: нужно преобразовать данные функциональный стиль .. code:: python nums = [1, 2, 3] list(map(lambda x: x * 2, nums)) # [2, 4, 6] filter() — фильтрация Используется, когда: нужно отфильтровать данные убрать лишние элементы .. code:: python nums = [1, 2, 3] list(map(lambda x: x * 2, nums)) # [2, 4, 6] 8. Функциональное программирование lambda — анонимная функция (ключевое слово) Используется, когда: нужно передать функцию как аргумент не хочется создавать отдельную функцию с def удобно в map, filter, sorted, key .. code:: python f = lambda x: x * 2 # создаём функцию x → x*2 print(f(5)) # 10 # Прямое использование в map nums = [1, 2, 3] list(map(lambda x: x**2, nums)) # [1, 4, 9] # В sorted с ключом words = ["apple", "banana", "kiwi"] sorted(words, key=lambda x: len(x)) # ['kiwi', 'apple', 'banana'] callable() — это встроенная функция, которая проверяет, можно ли объект вызвать как функцию Вызываемые объекты: функции методы классы (потому что вызывается конструктор) объекты с методом __call__() .. code:: python def f(): pass class A: def __call__(self): print("called") print(callable(f)) # True print(callable(A)) # True print(callable(A())) # True print(callable(123)) # False functools.reduce() — последовательно сворачивает коллекцию в одно значение .. code:: python from functools import reduce # 1 + 2 = 3 nums = [1, 2, 3, 4] # 3 + 3 = 6 result = reduce(lambda a, b: a + b, nums) # 6 + 4 = 10 print(result) # 10 9. Атрибуты и рефлексия getattr() - получить атрибут объекта Возвращает значение атрибута по имени. Используется, когда: нужно получить атрибут динамически имя атрибута хранится в строке .. code:: python class A: x = 10 a = A() getattr(a, "x") # 10 getattr(a, "y", 0) # 0 (значение по умолчанию) setattr() - установить атрибут объекта Присваивает значение атрибуту по имени. Используется, когда: нужно динамически изменить объект создание атрибутов на лет .. code:: python class A: pass a = A() setattr(a, "x", 5) print(a.x) # 5 delattr() — удалить атрибут объекта Удаляет атрибут по имени. Используется, когда: нужно удалить свойство объекта динамическая очистка .. code:: python class A: x = 10 a = A() delattr(a, "x") # print(a.x) ошибка, атрибут удалён hasattr() — проверка существования атрибута Возвращает True, если объект имеет атрибут с указанным именем. Используется, когда: безопасная работа с динамическими атрибутами проверка перед доступом или удалением .. code:: python class A: x = 10 a = A() hasattr(a, "x") # True hasattr(a, "y") # False vars() - словарь атрибутов объекта Возвращает __dict__ объекта (имена → значения). Используется, когда: нужно получить все атрибуты объекта интроспекция, сериализация .. code:: python class A: x = 10 y = 20 a = A() vars(a) # {'x': 10, 'y': 20} dir() - Возвращает список всех доступных атрибутов и методов объекта. Используется, когда: изучение объекта отладка и интроспекция .. code:: python class A: x = 10 a = A() dir(a) # ['__class__', '__delattr__', ..., 'x'] 10. Работа с кодом и выполнением eval() — вычисляет выражение, возвращает результат. Используется, когда: нужно динамически вычислить строковое выражение как Python‑код полезно для калькуляторов, парсеров простых выражений Важно: небезопасно использовать с ненадёжными данными (можно выполнить произвольный код). .. code:: python expr = "2 + 3 * 4" result = eval(expr) # 14 print(result) exec() — выполняет код из строки или объекта кода. Используется, когда: нужно выполнить несколько строк кода динамически например, скрипт формируется на лету Отличие от eval(): exec() не возвращает результат, выполняет код целиком подходит для нескольких выражений и блоков кода .. code:: python code = """ a = 10 b = 5 c = a + b """" exec(code) print(c) # 15 compile() — компилирует строку кода в объект кода для последующего выполнения Используется, когда: нужно подготовить код для eval() или exec() заранее можно оптимизировать многократное выполнение одного и того же кода .. code:: python code_str = "x + y" code_obj = compile(code_str, "", "eval") x, y = 2, 3 result = eval(code_obj) # 5 print(result) # Аргументы: # source — строка кода # filename — имя файла или источник (для сообщений об ошибках) # mode — "eval" (выражение), "exec" (блок кода), "single" (одна команда) Использовать осторожно. 11. Контекст и область видимости globals() — возвращает словарь глобальных имён текущего модуля. Используется, когда: нужно получить доступ к глобальным переменным по имени применяется в отладке, метапрограммировании, динамическом доступе к объектам .. code:: python x = 10 def show_globals(): print(globals()['x']) # доступ к глобальной переменной по имени show_globals() # 10 globals()['y'] = 20 print(y) # 20 locals() — возвращает словарь локальных имён текущей области видимости. Используется, когда: нужно посмотреть локальные переменные функции удобно для отладки и логирования .. code:: python def test(): a = 5 b = 7 print(locals()) # {'a': 5, 'b': 7} test() 12. Работа с файлами и системными объектами open() — — открывает файл для чтения или записи. Используется, когда: нужно работать с файлами на диске (текстовыми или бинарными) читать данные, записывать результаты, создавать новые файлы .. code:: python open(file, mode='r', encoding=None) 13. Ошибки и отладка help() — выводит справку о объекте (функции, классе, модуле). Используется, когда: нужно быстро узнать, как работает функция или метод изучаете новый модуль или библиотеку .. code:: python help(print) # справка о встроенной функции print help(str) # справка о типе str help("modules") # список доступных модулей breakpoint() — точка останова для отладки. Используется, когда: нужно остановить выполнение программы и войти в интерактивный режим отладки удобно для анализа состояния переменных в конкретной точке .. code:: python x = 10 y = 5 breakpoint() # здесь выполнение остановится, откроется pdb z = x + y print(z) 14. Специальные / служебные repr() — возвращает строковое представление объекта для разработчика. .. code:: python x = "Привет" print(repr(x)) # "'Привет'" — с кавычками, пригодно для eval() ascii() — возвращает строку с экранированием не-ASCII символов. .. code:: python s = "Привет" print(ascii(s)) # '\u041f\u0440\u0438\u0432\u0435\u0442' format() — форматирование строк. .. code:: python name = "Михаил" age = 42 print("Имя: {}, возраст: {}".format(name, age)) # Имя: Михаил, возраст: 42 slice() объект среза, используется для индексирования последовательностей. .. code:: python lst = [0,1,2,3,4,5] s = slice(1,5,2) # start=1, stop=5, step=2 print(lst[s]) # [1,3] object() — базовый объект Python, родитель всех классов. .. code:: python obj = object() print(type(obj)) # classmethod() — метод класса, получает класс как первый аргумент. .. code:: python class MyClass: @classmethod def hello(cls): print("Hello from", cls.__name__) MyClass.hello() # Hello from MyClass staticmethod() — статический метод, не принимает ни self, ни cls. .. code:: python class MyClass: @staticmethod def greet(): print("Привет!") MyClass.greet() # Привет! property() — создаёт управляемый атрибут (getter/setter). .. code:: python class Person: def __init__(self, name): self._name = name @property def name(self): return self._name p = Person("Михаил") print(p.name) # Михаил super() — доступ к родительскому классу. .. code:: python class A: def hello(self): print("Hello from A") class B(A): def hello(self): super().hello() print("Hello from B") b = B() # Hello from A b.hello() # Hello from B 15. Проверка итераций iter() — возвращает итератор из итерируемого объекта. Используется, когда: нужно пройтись по объекту шаг за шагом вручную работать с объектами, которые поддерживают итерацию (списки, строки, словари) .. code:: python lst = [1, 2, 3] it = iter(lst) # создаём итератор print(it) # next() — возвращает следующий элемент итератора. Используется, когда: нужно получать элементы итератора по одному можно задать значение по умолчанию, если элементы закончились .. code:: python lst = [1, 2, 3] it = iter(lst) print(next(it)) # 1 print(next(it)) # 2 print(next(it)) # 3 # print(next(it)) # StopIteration print(next(it, "Конец")) # Конец — вместо ошибки Строки документации ------------------- Python имеет строки документации, обычно обозначаемую сокращённо docstrings. Важный инструмент, помогает лучше документировать программу и облегчает её понимание. Строку документации можно получить, из функции, даже во время выполнения программы! .. code:: python def print_max(x, y): # Args: Выводит текст в подсказках при наведение на функцию """ Выводит наибольшее из двух чисел. Args: x (int): первое число y (int): второе число Returns: None """ x = int(x) # конвертируем в целые, если возможно y = int(y) if x > y: print(x, 'наибольшее') else: print(y, 'наибольшее') print_max(3, 5) print(print_max.__doc__) Изменяемые объекты в функции ---------------------------- При передаче изменяемых объектов в функцию, в случаи изменения объекта в функции объект в не функции тоже изменится. .. code:: python def add_item(items): # параметр — список (изменяемый объект) items.append("яблоко") # изменяем объект внутри функции basket = ["хлеб", "молоко"] # исходный список add_item(basket) # передаём список в функцию print(basket) # объект изменился и вне функции # Как избежать изменения внешнего объекта def add_item_copy(items): new_items = items.copy() # создаём копию new_items.append("яблоко") return new_items basket = ["хлеб", "молоко"] new_basket = add_item_copy(basket) print(basket) # исходный список не изменился print(new_basket) # изменённая копия Рекурсивная функция ------------------- Рекурсивная функция — это функция, которая вызывает саму себя. Она должна иметь условие выхода, иначе вызовы будут бесконечными, и программа завершится с ошибкой. .. code:: python def calc_f(num): if type(num) is not int: raise TypeError('integer') if num <= 0: raise ValueError('positive') if num == 1: return 1 return calc_f(num -1) * num # В рекурсивных вызовах сначала идёт углубление (убывание), а потом разворачивание (увеличение). calc_f('10') # Факториал 10! == 10*9*8*7*6*5*4*3*2*1 Присвоение переменой функции ---------------------------- В Python функции можно присваивать переменным, потому что функции — это объекты. .. code:: python def hello(): # (применяется для хранения в структуре данных (списки, словари) когда нужно выполнить несколько операций по очереди print("Привет!") greet = hello # Присваиваем функцию переменной # Теперь greet — это тоже hello greet() # Выведет: Привет! def outer(): # Возврат функции как переменную. (применяется для замыкания, фабрики функций) def inner(): print("Я внутри!") return inner # Без скобок! func = outer() # Теперь func = inner func() # Выведет: Я внутри! def double_call(func): # Передаем функцию как аргумент (применяется для сортировка, фильтрация) func() func() double_call(hello) Колбэк-функция -------------- Колбэк-функция (callback function) — это функция, которую передают в другую функцию как аргумент, чтобы она была вызвана позже или при наступлении события. .. code:: python def greet(name): print("Привет,", name) def process_user(name, callback): # callback — функция callback(name) # вызываем её внутри process_user("Анна", greet) Классы ------ Классы: Создание экземпляров на основе шаблонов Экземпляры наследуют атрибуты класса .. code:: python class Car: # имя класса net = 15 # Атрибут класса, обычно добавляют так константы для использования в других методах # тело класса Методы move() и stop() просто выполняют действия, но не изменяют состояние объекта. def move(self): # метод класса, self - указание на экземпляр Car.net +=1 # Обращение к атрибуту класса print('одно') def stop(self): # метод класса print('другое') my_car = Car() # Вызов my_car.move() # одно - Вызов метода my_car.stop() # другое - Вызов метода Car.net = 10 # изменение атрибута класса print(Car.net) # print(my_car) # <__main__.Car object at 0x000002727DEFBA90> print(dir(my_car)) # Видно атрибуты move, stop print(type(my_car)) # print(isinstance(my_car, Car)) # True print(my_car.__dict__) # {} Собственных атрибутов у my_car нет, move, stop наследуются от класса class Comment: # Comment хранит данные внутри объекта (self.text, self.votes_qty) def __init__(self, text): # магический метод для создания нового экземпляра # В этом классе у каждого комментария есть свои уникальные данные: текст и количество голосов. # __init__() создаёт эти данные (self.text и self.votes_qty) при создании объекта. # Без __init__() объект не смог бы хранить текст комментария. self.text = text # Собственные атрибуты self.votes_qty = 0 def upvote(self): self.votes_qty += 1 def upvote2(self, qty): self.votes_qty += qty # first_comment.upvote(5) передача аргумента 5 # first_comment предыдущее значение 1 сохраняется поэтому выдаст 6 print(first_comment) # <__main__.Image object at 0x0000023EF2D5A110> # необходимо вести ниже метод __str__ для того чтоб в консоль вывело текст # def __str__(self): # return f" {self.text}.{self.votes_qty}" first_comment = Comment("Первый комментарий") # Создание экземпляра print(first_comment.text) # Первый комментарий - чтение атрибута класса print(first_comment.votes_qty) # 0 - чтение атрибута класса (метод upvote() нигде не вызывается!) # first_comment.upvote() # Теперь вызываем метод votes_qty стал равен 1 # print(first_comment.votes_qty) Методы экземпляров и классов: Методы экземпляров - всегда получают self (ссылку на объект) Методы класса - привязаны не к объекту а к всему классу cls Статические методы - не привязаны ни к экземпляру, ни к классу. Они работают как обычные функции, но принадлежат классу. .. code:: python p1 = Player("Алекс") print(p1.greet) #Привязанные методы (bound) - Когда метод вызывается через объект (p1.greet()), # он привязывается к этому объекту. print(Player.greet) # Непривязанный метод (unbound) - Если метод вызывается напрямую через класс, он не привязан к объекту. потому что он вызывается через класс без объекта. Тип метода Привязанность Передаёт self или cls? Можно вызывать без объекта? Метод экземпляра Привязан к объекту self (экземпляр) Нет Метод класса Привязан к классу cls (класс) Да Статический метод Не привязан Нет self или cls Да .. code:: python class Car: @staticmethod # декоратор статического метода, не привязывается к экземпляру def move(net_parametra_self, two) return f"Просто действие" # Вызывать можно как науровне класса так и на уровне экземпляра Магические методы: В собственных классах надо реализовывать методы, чтоб можно было в не классе реализовать функционал .. code:: python print(ter + ret) # выдаст ошибку так как нету реализации магического метода __add__ в классе # реализация метода def __add__(self.text, other): return (f'{self.text} {other.text}', self.votes_qty + other.votes_qty) Наследие: .. code:: python class New_class(Roditelski_class): # наследуется из класса Roditelski_class def print(self): # Метод __init__ родительского класса вызывается автоматически print('blood') class User: def __init__(self, username, email): self.username = username self.email = email class AdminUser(User): def __init__(self, username, email, role): super().__init__(username, email) # super() создает объект который представляет User __init__ - доступ к методу self.role = role self.is_admin = True may_admin = dminUser('admin123', 'admin@ru.com', 'AdminIm') print(may_admin) Декоратры --------- Декоратор. — это функция, которая принимает другую функцию (или метод), изменяет её поведение и возвращает её обратно. Это мощный инструмент, который позволяет добавлять функциональность к функциям без изменения их кода. Используются для логирования, проверки прав, кэширования и других задач Можно применять к любым callable (функции, методы) Можно вкладывать декораторы друг в друга (цепочки) Декоратор может менять: аргументы функции поведение до/после вызова результат функции .. code:: python def decorator_function(original_fn): def wrapper_function(*args, **kwargs): # Функция для перехвата всех аргументов. *args, **kwargs - любые аргументы print("Код до оригинальной функции") # модифицирующий код до оригинальной функции result = original_fn(*args, **kwargs) # Вызов функции print("Function result:", result) # доступ к оригинальной функции print("Код после оригинальной функции") # модифицирующий код после оригинальной функции return result # ВАЖНО: Возвращаем результат оригинальной функции , если не возвращать выдаст None return wrapper_function # ВАЖНО: Возвращаем обернутую функцию (модифицированную с кодом до и после оригинальной функции) @decorator_function # передача функции ниже в декоратор на верху def my_function(a, b): # оригинальная функция print("This is my function!") return (a, b) result = my_function(100, 50) # вызов функции print(result) Декораторы: .. code:: python # @staticmethod — делает метод независимым от self экземпляра класса. # @classmethod — делает метод общим для всех объектов класса. # @property — превращает метод в атрибут геттер. # @.setter - Сеттер для свойства # @.deleter -Делетер для свойства # @abstractmethod — делает метод абстрактным, заставляя наследников реализовывать его. # @lru_cache Кэширует результаты функции # @wraps Сохраняет метаданные оригинальной функции # @singledispatch Перегрузка функции по типу аргумента # @contextmanager Упрощает создание менеджеров контекста # @dataclass Упрощает создание классов # @asyncio.coroutine / async def Асинхронное программирование # @functools.wraps — Сохраняет метаданные функции при декорировании (имя, docstring, аннотации) # @functools.lru_cache - Кэширует результаты вызовов функции # @functools.cache - Упрощённая версия lru_cache (без ограничения размера) # @functools.total_ordering - Достаточно определить __eq__ и один оператор сравнения # @functools.singledispatch - Функция с разной реализацией в зависимости от типа аргумента # @functools.singledispatchmethod - То же самое, но для методов класса # @abc.abstractmethod - Обязательный метод для наследников # @enum.unique - Запрещает одинаковые значения в Enum # @dataclasses.dataclass - Автоматически генерирует __init__, __repr__, __eq__ и др. # @contextlib.contextmanager - Позволяет писать контекстный менеджер через yield # @typing.final - Позволяет проверять Protocol через isinstance # @coroutine - Старый способ работы с корутинами (устаревающий) # @warnings.deprecated - Помечает функцию как устаревшую (новые версии Python) Порядок выполнения нескольких декораторов .. code:: python @A @B @C def func(): pass # Эквивалентно: func = A(B(C(func))) Декораторы применяются снизу вверх, выполняются (при вызове функции) сверху вниз. .. code:: python def deco_a(func): print("A: декорируем") def wrapper(): print("A: до вызова") func() print("A: после вызова") return wrapper def deco_b(func): print("B: декорируем") def wrapper(): print("B: до вызова") func() print("B: после вызова") return wrapper @deco_a @deco_b def hello(): print("HELLO") Логирование .. code:: python def log_function_call(fn): def wrapper(*args, **kwargs): print(f"Function name: {fn.__name__}") # Логирование {fn.__name__} - магический атрибут дающий доступ к названию функции print(f"Function arguments: {args}, {kwargs}") # Логирование аргументов result = fn(*args, **kwargs) print(f"Function result: {result}") # Логирование результата return result return wrapper @log_function_call def mult(a, b): return a * b print(mult(5, 2)) # валидатор аргументов def validate_args(fn): def wrapper(*args, **kwargs): for arg in [*args, *kwargs.values()]: # values() - доступ к всем значениям if not isinstance(arg, int) and not isinstance(arg, float): raise ValueError(f"Type of the {arg} is {type(arg)}", "All arguments must be int or float!") return fn(*args, **kwargs) return wrapper @validate_args def sum_nums(a, b): return a + b try: print(sum_nums(7, 2)) print(sum_nums(10.5, 2.3)) print(sum_nums([1, 2, 3], '2.0')) print(sum_nums(a=10.5, b='2.0')) except ValueError as e: print(e) Инспекция и dunder-атрибуты --------------------------- Инспекция объектов (Introspection) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: python print(dir(obj)) # Показывает список всех доступных атрибутов и методов объекта print(id(obj)) # Показывает уникальный идентификатор (адрес в памяти) print(type(obj)) # Показывает тип (класс) объекта print(help(obj)) # Показывает встроенную справку по объекту print(obj.__doc__) # Показывает строку документации (docstring) print(obj.__dict__) # Словарь атрибутов объекта print(obj.__class__) # Класс, к которому принадлежит объект print(obj.__module__) # Модуль, в котором определён объект print(obj.__annotations__) # Аннотации типов (если есть) print(obj.__sizeof__()) # Размер объекта в байтах from sys import getsizeof print(getsizeof(obj)) # Альтернатива — учитывает служебную информацию Информация о классах и наследовании ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: python print(MyClass.__subclasses__()) # Список всех подклассов данного класса print(MyClass.__bases__) # Кортеж базовых (родительских) классов print(MyClass.__mro__) # Порядок разрешения методов (Method Resolution Order) print(MyClass.__name__) # Имя класса Магические методы (Dunder methods) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Строковые представления .. code:: python obj.__repr__() # “Официальное” строковое представление (для разработчиков) obj.__str__() # “Человеческое” строковое представление (для вывода) Хэш и сравнения .. code:: python obj.__hash__() # Возвращает хэш-значение объекта obj.__eq__(x) # Равно == obj.__ne__(x) # Не равно != obj.__lt__(x) # Меньше < obj.__le__(x) # Меньше или равно <= obj.__gt__(x) # Больше > obj.__ge__(x) # Больше или равно >= Прочие специальные атрибуты ^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: python obj.__slots__ # Определяет допустимые атрибуты (ограничивает __dict__) Обработка ошибок ---------------- .. code:: python try: pass # блок кода который выполняется except ErrorType: # тип ошибки, если словил этот тип то pass # в случаи ошибки в try выполнится блок кода except # Если корректно обработали ошибку, то Python не останавливает выполнение кода except ErrorType as e: # присваивает ошибке имя , можно в try несколько except print(type(e)) # выведет текст ошибки else: # если не сработало не одно исключение finally: # выполняется в любом случаи try: pass # блок кода который выполняется except Exception as e: # если не знаешь какая ошибка print(e) # Почему не стоит использовать Exception # Ловля конкретных ошибок делает код более читаемым и предсказуемым # Ловля только нужных ошибок помогает избежать нежелательного подавления других исключений # Обработка Exception может замаскировать баги # Более точная обработка ошибок позволяет лучше реагировать на ситуацию # Исключения выше Exception (например, SystemExit, KeyboardInterrupt) не обрабатываются явно # Когда использовать Exception: # Когда вы точно не знаете, какие ошибки могут возникнуть (например, в тестовой среде или временном коде). # Для логирования всех ошибок, если ваш код затем завершает работу или пересылает ошибку. raise # используется для генерации исключений. Оно позволяет "поднять" ошибку вручную, когда в коде возникает нежелательная ситуация, или передать исключение выше по стеку вызовов. def set_age(age): # Пример if age < 0: raise ValueError("Возраст не может быть отрицательным") print(f"Возраст установлен: {age}") set_age(-5) # Пример подключение к БД - подключение в try, другие действия в else так как ошибок не возникло , отключение finally Хорошая практика перенаправлять ошибки на отдельный сервис логирования Хорошая практика обрабатывать ошибки в функции Типы ошибок стандартной библиотеке Python: .. code:: ArithmeticError Базовый класс для всех ошибок, связанных с математическими операциями. AssertionError Возникает при неудачном выполнении инструкции assert. AttributeError Обращение к несуществующему атрибуту объекта. BaseException Базовый класс для всех исключений (включая SystemExit, KeyboardInterrupt, и GeneratorExit). BufferError Ошибка, связанная с операциями буфера. BytesWarning Предупреждение о проблемах с байтовыми строками (только для режима -b). DeprecationWarning Предупреждение об использовании устаревших функций. EOFError Ошибка при достижении конца файла или потока, где это не ожидается. Exception Базовый класс для большинства исключений (не включая SystemExit, KeyboardInterrupt и GeneratorExit). FileExistsError Возникает при попытке создания файла, который уже существует. FileNotFoundError Указанный файл или директория не найдены. FloatingPointError Ошибка, связанная с операциями с плавающей точкой (редко возникает). FutureWarning Предупреждение о предстоящих изменениях в функциональности. GeneratorExit Вызывается при закрытии генератора. ImportError Ошибка при импорте модуля. ModuleNotFoundError: Подкласс, вызывается, если модуль не найден. IndentationError Ошибка синтаксиса, вызванная неверными отступами. TabError: Подтип, возникающий при смешении пробелов и табуляции. IndexError Индекс выходит за границы последовательности. KeyError Обращение к несуществующему ключу в словаре. KeyboardInterrupt Прерывание программы пользователем (например, Ctrl+C). LookupError Базовый класс для ошибок поиска (например, IndexError или KeyError). MemoryError Превышение доступной памяти. NameError Использование имени, которое не определено. UnboundLocalError: Подтип, если локальная переменная используется до её определения. NotADirectoryError Попытка обратиться к объекту, который не является директорией. NotImplementedError Метод или функция не реализованы. OSError Ошибка, связанная с операционной системой (например, работа с файлами). Подклассы: BlockingIOError Операция ввода-вывода заблокирована в неблокирующем режиме. ChildProcessError Ошибка при работе с дочерними процессами (например, ожидание несуществующего процесса). ConnectionError Базовый класс для ошибок соединения. и его подклассы: BrokenPipeError Соединение или канал разорваны. ConnectionAbortedError Соединение было прервано другой стороной. ConnectionRefusedError Соединение отклонено (например, сервер не отвечает). ConnectionResetError Соединение сброшено другой стороной. FileExistsError Попытка создать файл или директорию, которая уже существует. FileNotFoundError Указанный файл или директория не найдены. IsADirectoryError Операция ожидала файл, но путь указывает на директорию. NotADirectoryError Операция ожидала директорию, но путь указывает на файл. PermissionError Недостаточно прав для выполнения операции. ProcessLookupError Указанный процесс не найден. TimeoutError Время ожидания операции истекло. OverflowError Результат вычислений слишком велик для представления. PendingDeprecationWarning Предупреждение о функциональности, которая будет устаревать в будущем. PermissionError Недостаточно прав для выполнения операции. ProcessLookupError Указанный процесс не найден. RecursionError Превышен лимит рекурсии. ReferenceError Попытка доступа к объекту через слабую ссылку, когда объект уже удалён. ResourceWarning Предупреждение о неправильном использовании ресурсов (например, не закрытый файл). RuntimeError Общая ошибка выполнения, не подпадающая под другие категории. SyntaxError Ошибка синтаксиса. IndentationError: Подтип, связанный с неверными отступами. TabError: Смесь пробелов и табуляций. SystemError Внутренняя ошибка интерпретатора. SystemExit Исключение для выхода из программы (например, вызов sys.exit()). TabError Смесь пробелов и табуляции в отступах. TimeoutError Истечение времени выполнения операции. TypeError Некорректная операция с объектами неподходящего типа. UnboundLocalError Локальная переменная используется до её определения (подтип NameError). UnicodeDecodeError Ошибка декодирования строки Unicode. UnicodeEncodeError Ошибка кодирования строки Unicode. UnicodeError Базовый класс для ошибок Unicode. UnicodeTranslateError Ошибка преобразования строки Unicode. UserWarning Пользовательское предупреждение. ValueError Некорректное значение передано функции или методу. Warning Базовый класс для предупреждений. ZeroDivisionError Деление на ноль. Изменяемость, идентичность, копирование --------------------------------------- Тип данных и их свойства ^^^^^^^^^^^^^^^^^^^^^^^^ +-------+------------+------------------+---------------------+ | list | Изменяемый | упорядоченный | одинаковые элементы | +-------+------------+------------------+---------------------+ | tuple | нет | упорядоченный | одинаковые элементы | +-------+------------+------------------+---------------------+ | set | Изменяемый | нет | нет | +-------+------------+------------------+---------------------+ | range | нет | упорядоченный | нет | +-------+------------+------------------+---------------------+ | dict | Изменяемый | нет | нет | +-------+------------+------------------+---------------------+ | str | нет | упорядоченный | одинаковые элементы | +-------+------------+------------------+---------------------+ Адреса объектов в памяти ^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: python m_n = 10 print(id(m_n)) # 2798471414288 o_n = 10 print(id(o_n)) # 2798471414288 c_n = m_n print(id(m_n)) # 2798471414288 print(id(c_n)) # 2798471414288 c_n += 5 # создаётся новый объект print(id(m_n)) # 2798471414288 print(id(c_n)) # другой адрес **Примечание:** неизменяемые объекты (int, str, tuple) при изменении создают новую копию в памяти, а изменяемые (list, dict, set) — работают по ссылке. Поверхностное и глубокое копирование ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: python from copy import deepcopy info_deepcopy = deepcopy(словарь) # Возвращает новый объект с копиями всех вложенных структур. def copy_fn(person): person_copy = person.copy() # поверхностная копия person_copy["age"] += 2 return person_copy **Разница:** `copy()` создаёт копию только верхнего уровня (не вложеные объекты). `deepcopy()` — рекурсивно копирует все вложенные объекты. `=` просто создаёт новую ссылку на тот же объект в памяти. Принципы ООП ============ Инкапсуляция, Наследование, Полиморфизм, Абстракция. Инкапсуляция — это когда мы скрываем детали реализации внутри класса и предоставляем только нужные методы для работы с объектом. .. code:: python class Email: def __init__(self, sender, recipient, subject, body): self.sender = sender # Закрытая переменная (инкапсуляция) self.recipient = recipient self.subject = subject self.body = body def send_email(self): # Логика отправка писем pass def deposit(self, amount): if amount > 0: self.__balance += amount # Доступ к данным через метод else: print("Сумма должна быть положительной!") def get_balance(self): return self.__balance # Доступ только через метод def read_email(self): # Логика чтения писем pass # print(account.__balance) # Ошибка! Прямой доступ запрещён # Инкапсуляция защищает данные и скрывает детали, позволяя работать # только с нужными частями объекта. Наследование - позволяет одному классу (наследнику) наследовать свойства и методы другого класса (родителя). Это позволяет переиспользовать код и создавать более специфичные классы на основе более общих. .. code:: python class Animal: # Родительский класс def __init__(self, name): self.name = name def speak(self): return "Some sound" class Dog(Animal): # Дочерний класс, наследует от Animal def __init__(self, name, breed): # Конструктор для Dog super().__init__(name) # Вызов конструктора родителя (Animal) self.breed = breed # Дополнительный атрибут breed для собаки # Когда мы хотим расширить функциональность конструктора родительского класса. # Это позволяет инициализировать атрибуты родительского класса и добавить новые # атрибуты в дочернем классе. def speak(self): # Переопределение метода speak parent_sound = super().speak() # Вызов метода родительского класса # Сохраняем функциональность родителя и добавляем свою. # Это важно, когда нужно не просто заменить поведение родительского метода, но # и добавить новое поведение без потери того, что уже реализовано в родителе. return parent_sound + " and Woof!" # Дополняем вывод дополнительным звуком class Cat(Animal): # Другой дочерний класс, также наследует от Animal def speak(self): # Переопределение метода speak return "Meow!" # Создаём объекты dog = Dog("Buddy") cat = Cat("Whiskers") print(dog.name) # Buddy print(dog.speak()) # Woof! print(cat.name) # Whiskers print(cat.speak()) # Meow! # Наследование — это способ переиспользовать и расширять функциональность # классов, создавая более сложные и специализированные объекты, # базируясь на общих классах. Полиморфизм - способность методов (функций) работать по-разному в зависимости от объекта, который их вызывает. Когда один и тот же метод (или оператор) делает разное в зависимости от объекта. Это делает код гибким, удобным и читаемым! .. code:: python # Родительский класс class Animal: def make_sound(self): return "Какой-то звук" # Базовое поведение # Дочерний класс, переопределяющий метод class Dog(Animal): def make_sound(self): # Переопределение метода родителя return "Гав-гав!" # Дочерний класс, переопределяющий метод class Cat(Animal): def make_sound(self): # Переопределение метода родителя return "Мяу!" # Дочерний класс, который вызывает метод родителя через super() class Fox(Animal): def make_sound(self): return super().make_sound() + " но конкретно я говорю Фррр!" # Расширение метода родителя # Функция, которая работает с разными объектами (полиморфизм) def animal_sound(animal): print(animal.make_sound()) # Создаём объекты разных классов dog = Dog() cat = Cat() fox = Fox() # Вызываем одну и ту же функцию с разными объектами (полиморфизм) animal_sound(dog) # Выведет: "Гав-гав!" animal_sound(cat) # Выведет: "Мяу!" animal_sound(fox) # Выведет: "Какой-то звук но конкретно я говорю Фррр!" def add(a, b): # полиморфизм через функцию return a + b print(add(1, 2)) # Выведет: 3 print(add("Hello, ", "world!")) # Выведет: Hello, world! # Сначала ищет метод в самом объекте (его классе) поиска методов идёт снизу вверх. # Если не находит, поднимается выше по иерархии классов (ищет в родительском классе). # Если находит, вызывает его. # Если метод не найден AttributeError Полиморфизм без наследования .. code:: python class Dog: def sound(self): return "Woof" class Cat: def sound(self): return "Meow" animals = [Dog(), Cat()] for animal in animals: print(animal.sound()) # Полиморфизм работает через одинаково названные методы в разных классах. Абстракция — это процесс выделения только ключевых характеристик объекта, игнорируя все лишнее. Мы создаем упрощенную модель или интерфейс, оставляя детали реализации скрытыми. .. code:: python from abc import ABC, abstractmethod class Transport(ABC): # Делаем класс абстрактным @abstractmethod # декоратор обязывает все дочернии классы прописывать этот метод иначе ошибка # Класс Bicycle не реализует абстрактный метод travel() def travel(self): pass class Car(Transport): def travel(self): return "Поехал на машине" class Bus(Transport): def travel(self): return "Поехал на автобусе" class Train(Transport): def travel(self): return "Поехал на поезде" # Реальная жизнь: у нас есть несколько видов транспорта vehicles = [Car(), Bus(), Train()] for vehicle in vehicles: print(vehicle.travel()) # Вызывает нужный метод в зависимости от типа объекта Преимущества абстракции: Упрощение работы с системой. Мы не погружаемся в детали реализации, а используем высокоуровневые интерфейсы. Гибкость и масштабируемость. Можно добавлять новые классы, не меняя код, который использует абстракцию. Снижение сложности. Мы скрываем сложные детали, оставляя только то, что важно для пользователя. Когда используется абстракция: При проектировании интерфейсов. Когда нужно скрыть реализацию, оставив только важные для пользователя части. В крупных системах, где взаимодействие происходит через интерфейсы, а не через детали реализации. Модули ====== .. include:: Built_in_module.rst Файлы байткода .pyc ^^^^^^^^^^^^^^^^^^^ Библиотеки ========== Фреймворки ========== Практика ======== Генераторы Память Диапазоны Биты и байты