Высокоуровневый язык программирования общего назначения Python ориентирован на повышение производительности разработчика и читаемости кода; синтаксис ядра минималистичен; поддерживает структурное, обобщенное, объектно-ориентированное, функциональное и аспектно-ориентированное программирование. Основные архитектурные черты — динамическая типизация, автоматическое управление памятью, полная интроспекция, механизм обработки исключений, поддержка многопоточных вычислений, высокоуровневые структуры данных. Поддерживается разбиение программ на модули, которые, в свою очередь, могут объединяться в пакеты.
Настоящая публикация содержит конспект изучения языка Python разработчиком привыкшим к классическим языкам (Pascal, C++, Java). Изложение в публикации будет простым, наглядным и слегка вульгарным, как и сама идеология Python.
- Официальный сайт //www.python.org
- Довідник з мови Python //docs.python.org/uk/3/reference/index.html
- Python 3.9.0 documentation //docs.python.org
- Built-in Constants .../3/library/constants.html
- Built-in Functions .../3/library/functions.html
- Built-in Types .../3/library/stdtypes.html
- Python 3.8.6 download //www.python.org/downloads
- Anaconda Individual Edition (Data science toolkit Free Download) //www.anaconda.com
- Бесплатный курс "Python: Основы программирования" //ru.hexlet.io
- ...и другие источники в конце публикации
Версии языка Python
Python 1.0 был выпущен в январе 1994 года.
В декабре 2008 года был выпущен Python 3.0, также именуемый Python 3000 или Py3k. В версии 3.0 устранены многие архитектурные недостатки и с версиями 2.x она ограничено совместима.
Последняя на момент публикации актуальная версия 3.11 выпущена 5 апреля 2023 года.
Программный код
Исходный программный код Python состоит из последовательности операторов (statement). Каждый оператор располагается в отдельной строке, поэтому конец оператора синтаксически никак не обозначается.
Попытка разместить несколько операторов в одной строке приводит к синтаксической ошибке.
Строку оператора можно разделить на несколько строк, при этом перенос на следующую строку обозначается символом \, но в некоторых случаях символ переноса не используется.
Некоторые операторы образуют конструкции из нескольких строк. Синтаксическая связь между операторами в конструкции выражается отступом перед каждым оператором, который у операторов в конструкции должен быть идентичным.
Операторы, которые выполняются последовательность образует синтаксическую конструкцию блока операторов, и отступ у всех операторов в блоке должен быть идентичным.
Условные операторы, операторы цикла и некоторые другие создают ветку потока выполнения, которая обозначается большим отступом операторов. Завершение блока операторов ветки никак специально не обозначается. Первый оператор с меньшим отступом обозначает завершение блока.
Синтаксическую связь в конструкции или блоке операторов выражает отступ перед началом оператора, отступ при переносе строки может быть произвольным.
Основные примитивы
Присваивание в Python на первый взгляд не отличается от классических языков:
1 2 3 4 5 6 |
one = 1 # оператор присваивания half = one / 2 # конец строки завершает синтаксическую конструкцию one = 3 // 2; half = 3 % 2 # некоторые синтаксические конструкции можно записать в одной строке, разделив точкой с запятой d = (one # синтаксическая конструкция может использовать несколько строк, + half * 2 # если обрамлена скобками (), [] или {} + c) |
Однако важно понимать, что любая переменная Python является объектом (физический идентификатор объекта можно получить функцией id(...)). Присваивание по сути является ассоциированием имени с объектом-значением, что принципиально отличается от классических языков, в которых присваивание является копированием значения в идентифицируемую область памяти. Детальней это принципиальное отличие описано в публикации "Указатели в Python: в чём суть?". Пример:
1 2 3 4 5 6 |
one = 1 # объект "простого" типа int равный 1 ассоциирован с именем 'one' id(one) # 1935699044688 - идентификатор объекта с именем 'one' one += 1 # инкрементирование объекта создает новый объект с новым идентификатором id(one) # 1935699044720 one += 1 # новый объект может получить идентификатор ранее утилизированного объекта id(one) # 1935699044688 |
Python позволяет выполнить множественное присваивание, в котором сначала вычисляются все выражения правой части, а затем ассоциируются (присваиваются) с именами в левой части:
1 2 3 |
a, b = b, a # выражение перестановки значений a и b # является предметом концептуальной гордости Python prev, next = next, prev+next # выражение для цикла вычисления ряда Фибоначи |
Версия Python 3.8 добавила возможность walrus, которая позволяет выполнить присваивание внутри выражения. Аналогичная возможность изначально была в C++, и хорошо что Python это заметил через 26 лет:
1 2 3 4 5 6 7 8 9 10 11 |
# цикл обработки команд до получения "quit" while true: cmd = input("cmd: ") if cmd != "quit": docmd(cmd) else: break # этот же цикл с использованием walrus while (cmd := input("cmd: ")) != "quit": docmd(cmd) |
///
Числа /типы int, float, complex
Числа в Python бывают целыми и "плавающими", для них определены операции +, -, *, ** (степень), /, // (целочисленное деление), % (остаток от деления). К плавающему значению приводит любое деление, а в остальных операциях, только если хоть один из операндов был плавающим. Самым удивительным результатом является остаток целочисленного деления плавающего:
1 2 3 4 5 6 7 8 9 10 |
print(8*2, 8*4/2) # 16 16.0 # тип результата умножения зависит от типов множителей print(8**2, 8**2.0) # 64 64.0 # тип результата степени зависит от обоих типов print(8**25) # 37778931862957161709568 # целочисленный результат степени может быть очень-очень большим print(-8**2, (-8)**2) # -64 64 # приоритет степени выше унарного минуса и других арифметических операций print(8/4, 8/3) # 2.0 2.6666666666666665 # результат деления всегда плавающий print(8//3, 8%3) # 2 2 # целочисленное деление целого и его целочисленный остаток print(-8//3, -8%3) # -3 1 # целочисленное деление и остаток для отрицательного целого print(8.2//3, 8.2%3) # 2.0 2.1999999999999993 # целочисленное деление плавающего остается плавающим, а остаток можно объяснить с большим трудом! print(-8.2//3, -8.2%3) # -3.0 0.8000000000000007 # целочисленное деление отрицательного плавающего и удивительный остаток print(int(8/3), int(-8/3)) # 2 -2 # приведение к целому положительного и отрицательного плавающего функцией int() |
Строка <class 'str'>
Текстовые данные в Python представляются строками - объектам класса str. Строки представляют собой неизменяемые последовательности кодовых точек Unicode.
В Python 3.x строки используют кодировку UTF-8.
Значения строк можно задавать литералами обрамленными парой ' или ", которые синтаксически равнозначны. Способы:
1 2 3 4 5 6 7 8 9 10 11 |
'abc' == "abc" # одиночные и двойные кавычки синтаксически эквивалентны 'a"b"c' == "a\"b\"c" # включение двойных кавычек в строковую константу "a'b'c" == 'a\'b\'c' # включение одиночных кавычек в строковую константу "c:\bool" == "cool" # обратный слеш служит признаком одного из служебных символов (в примере: "\b" - забой) 'c:\\bool' == r'c:\bool' # включение слеш в строковый литерал с подавлением экранирования ('multy ' # определение строкового литерала серией фрагментов 'parts ' 'of string') '''multy # тройные кавычки определяют многострочный литерал в естественном виде lines''' == 'multy\nlines' b'abc' != 'abc' # строка байтов может быть задана литералом, но строкой не является |
Перед строковым литералом может использоваться префикс в верхнем или нижнем регистре:
- f делает строку форматным шаблоном, который может содержать выражения замены в фигурных скобках {}, вычисляемые во время выполнения; добавлено в Python 3.6
- r подавляет экранирование в литерале:
1r'\n' == '\\n' - u представляет строку кодов unicode, которые будут преобразованы к строке:
1u'\u041F\u0440\u0438\u0432\u0456\u0442' == 'Привіт' - b представляет байтовый литерал, создающий экземпляр типа bytes (а не str); в литерале допустимы только печатные символы ASCII и escape-последовательности:
1b'\xEF\xBB\xBFExample with BOM'
Конец строки не зависит от входящих в строку символов (строку не завершает какой-либо символ, подобно \x00 в С++). Полную длину строки возвращает функция len(...):
1 |
print(len('abc\n\0')) # 5 |
Для строк определены операции взаимного сложения, умножение на число подразумевает сложение строки с собой:
1 |
'bla'+'bla' == 'bla' * 2 # конкатенация и умножение строк |
Строка являются также python-списком (будет описан ниже), который предусматривает итератор, перечисляющий все символы строки.
1 2 |
for char in 'ABC': # итератор списка символов строки print(char, end='-') # A-B-C- |
///
Составные типы данных
В Python предусмотрено несколько составных (compound) типов данных, используемых для группировки других значений, которые привычно называют коллекциями.
Список <class 'list'>
Список в Python аналогичен классическому массиву и является объектом упорядоченной коллекции значений, которые заключены в квадратные скобки и разделены между собой запятыми:
1 2 3 4 5 6 |
a = [] # пустой список b = [0, 1, [2, 3]] # список включающий другой список c = list('ABC') # ['A', 'B', 'C'] список из литер строки d = list(range(5)) # [0, 1, 2, 3, 4] список диапазона значений e = [x*3 for x in d] # [0, 3, 6, 9, 12] генератор на основе другого списка d f = [x**2 for x in e if x % 2 == 0] # [0, 36, 144] генератор на основе другого списка с условием |
Срез (slice?)
Срез списка - это новый список <class 'list'>, содержащий подмножество элементов коллекции исходного списка. Способ задания параметров среза очень напоминает цикл for из C++, в котором задается начальное значение индекса, значение индекса прекращающего цикл, шаг приращения индекса:
1 2 3 4 5 6 7 8 |
a = list(range(8)) # [0, 1, 2, 3, 4, 5, 6, 7] print(a[1]) # 1 # это не срез, а значение по индексу 1 print(a[1:]) # [1, 2, 3, 4, 5, 6] # срез от индекса 1 до конца print(a[-7:]) # [1, 2, 3, 4, 5, 6] # отрицательный индекс отсчитывается в обратном направлении от "запредела" списка print(a[1:5]) # [1, 2, 3, 4] # срез от индекса 1 до индекса 5 /"до" в исключительном смысле print(a[:5:2]) # [0, 2, 4] # срез от начала до индекса 5 с шагом 2 print(a[1:5:2]) # [1, 3] # срез использует от, до и шаг print(a[-1::-1]) # [7, 6, 5, 4, 3, 2, 1, 0] # срез от конца в обратном порядке /похож на метод a.reverse() |
Кортеж <class 'tuple'>
Кортеж в Python очень похож на список, в котором ни последовательность, ни элементы не могут измениться, в прочем, если элемент в кортеже сам относится к составному типу, то его содержание может измениться, но не сам элемент в кортеже. Элементы кортежа заключаются в круглые скобки и разделены между собой запятыми:
1 2 3 4 5 6 7 8 9 |
а = 0, 1, 2, 3, 4, 5, 6, 7 # (0, 1, 2, 3, 4, 5, 6, 7) # в определении кортежа скобки не обязательны b = (1, ) # определение кортежа из одного элемента имеет нюанс, поскольку просто (1) является числом print(a[1]) # 1 # это не срез, а значение по индексу 1 print(a[1:]) # (1, 2, 3, 4, 5, 6) # срез от индекса 1 до конца print(a[-7:]) # (1, 2, 3, 4, 5, 6) # отрицательный индекс отсчитывается в обратном направлении от "запредела" кортежа print(a[1:5]) # (1, 2, 3, 4) # срез от индекса 1 до индекса 5 /"до" в исключительном смысле print(a[:5:2]) # (0, 2, 4) # срез от начала до индекса 5 с шагом 2 print(a[1:5:2]) # (1, 3) # срез использует от, до и шаг print(a[-1::-1]) # (7, 6, 5, 4, 3, 2, 1, 0) # срез от конца в обратном порядке |
Множество <class 'set'>
Множество Python является неупорядоченной коллекцией уникальных значений, которые заключены в фигурные скобки и разделены между собой запятыми, при этом определить литералом пустое множество нельзя:
1 2 3 |
а = {1, 3, 5, 7} # {0, 1, 2, 3, 4, 5, 6, 7} # в определении кортежа скобки не обязательн b = set('aeiou') # c = set('') # |
Словарь <class 'dict'>
Словарь Python является неупорядоченной коллекцией с доступом к каждому элементу по уникальному ключу, сходно классической структуре и php-массиву. Элементы словаря заключаются в фигурные скобки и состоят из пар ключ:значение разделенных между собой запятыми:
1 |
a = {0:'zero', 1:'one', 2:'two', 3:'three'} |
Для словаря недоступен итератор, тем не менее из словаря методом .items() можно получить объект типа <class 'dict_items'>, который по сути является списком кортежей, или использовать список ключей метода .keys() и список значений метода .values() совмещенных функцией zip(...):
1 2 3 4 5 |
a = {0:'zero', 1:'one', 2:'two', 3:'three'} for kv in a.items(): # итератор элементов print(kv[0],kv[1]) for k, v in zip(a.keys(), a.values()): # итератор совмещенных списков ключей и значений print(k,v) |
Управление потоком выполнения
Блоки кода в Python определяется отступом форматирования, а не синтаксическими средствами, как в классических языках. По стандарту отступ должны формировать четыре пробела, табуляция не допускается (попытка использовать табуляцию вызывает ошибку, т.к. табуляция воспринимается в качестве символа начала выражения).
Блоки
Тернарный оператор в выражении с условием
Выражение с тернарным оператором использует синтаксис:
true_expr if condition else false_expr
//
1 |
text = ('' if not introduction is None else introduction + '\n') + content |
Условный оператор /if, elif, else
///
е в выражение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
if a < 0: print("negative") elif 1 <= a <= 5: print("positive") elif a == 0: print("zero") elif a is b: print("equivalent to b") elif a != None: print("other value") else: print("value is absent") A = Y if X else Z # |
///
1 |
A = Y if X else Z # |
Python реализует ленивое вычисление условия, т.е. выражение условия вычисляется от начала и до тех пор, пока его результат нельзя предсказать.
Оператор цикла /while, continue, break, else
//
1 2 3 4 5 6 |
value = 0; valueMax = 10; valueSum = 0 while value <= valueMax: value += 1 valueSum = valueSum + value print(valueSum) #else: !!! |
//
Оператор цикла /for, continue, break, else
//
Списки, кортежи, множества и словари могут быть соединены для синхронной итерации в цикле функцией zip(...), при этом число итераций будет определено самой короткой коллекцией:
1 2 3 4 5 6 |
c = ('', 'First', 'Second') l = [0, 1, 2, 3] s = {'', 'a', 'b', 'c', 'd'} d = {0:'zero', 1:'one', 2:'two', 3:'three'} for cv, lv, sv, dkv in zip(c, l, s, d.items()): print(cv, lv, sv, dkv[0], dkv[1]) |
Функция enumerate(...) возвращает полученный из объекта коллекции объект типа <class 'enumerate'>, итератор которого содержит индекс:
1 2 3 4 5 |
a = set('abc') # порядок элементов в множестве непредсказуем for i, c in enumerate(a): print(i, c) # 0 b # 1 c # 2 d |
/
Оператор бездействия (pass)
Синтаксис Python не позволяет оставить блок условия или цикла (после двоеточия) пустым, но если так нужно сделать, то следует использовать Pass:
1 2 |
while condition: # цикл с условием зависящим от другого потока pass # пустой блок цикла |
Оператор обработки исключений (try, except, finally, ...)
///
Оператор контекстного блока /with
Выражение применяется с объектами являющимися менеджерами контекста, как альтернатива каскаду выражений try...finaly.
1 2 |
with EXPRESSION as TARGET: SUITE |
Функции и методы
Функции и методы Python используются сходным
- function()
- modul.function()
- typename.type_method()
- class.static_method()
- object.method()
Функции и методы в большинстве случаев зависят от параметров, для которых определен порядок следования и имена параметров. Параметры могут передаваться в функцию или метод несколькими способами:
- последовательность значений в порядке установленном в определении метода
- последовательность именованных значений в произвольном порядке !!!!
предоставляет Вызов функции print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
1 2 |
print(a, b, c) print(a, b, c, sep=',', end='') |
Определение (Def, Return)
def cheeseshop(kind, *arguments, **keywords):
Параметры
//
В объявлении функции символ * перед параметром означает, что этот параметр является неопределенным количеством позиционных аргументов. Такой параметр обычно называется "args" и представляется в виде кортежа, который будет доступен внутри функции через параметр args:
1 2 3 4 5 |
def my_function(*args): for arg in args: print(arg) my_function(1, 2, 3) # prints>... |
Все параметры передаются в функцию по ссылке и могут быть изменены, если этого надо избежать, следует создать копию параметра (хотя есть нюансы):
1 2 3 |
def my_func(x): x = x.copy() ... |
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
Лямбда функции
my_func = lambda a, b: a + b
my_func(1, 2)
Генераторы
Генерация динамических последовательностей, которые не размещаются в памяти выполняется с помощью ключевого слова yield !!!
Пакеты
!!! Пакеты !!! Получить список доступных модулей #linux ssh:
1 2 3 |
pydoc modules #windows shell py -m pydoc modules |
Получить список доступных модулей win-команда:
1 |
py -m pydoc modules |
Команда Python:
help('modules')
Добавление модулей утилитой PIP
Python предусматривает неограниченное расширение базовой функциональности через дополнительные пакеты, для управления которыми используется специальная утилита \Program Files\Python*\Scripts\pip.exe. Утилита позволяет просматривать, устанавливать, удалять и обновлять пакеты командами в командной строке OS.
Список пакетов установленных PIP вызывает команда:
1 |
pip freeze |
Установка нового пакета в полной и сокращенной форме:
1 2 |
python.exe -m pip install numpi pip install numpi |
В случаях, когда установка вызывает предупреждения, может помочь удаление пакета и переустановка
1 |
pip uninstall numpi |
Утилита pip предусматривает возможность обновления самой утилиты pip:
1 |
python.exe -m pip install --upgrade pip |
Ошибка ModuleNotFoundError: No module named 'pip'
Если любые операции с пакетами завершаются ошибкой No module named 'pip', то возможно утилита повреждена и следует загрузить и выполнить установочный файл get-pip.py:
1 2 |
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py |
Пакет numpy
//numpy.org/doc/stable/user/index.html
Пакет json
//
1 2 3 4 5 6 7 |
import json dataset = [[[5, 3, 1, 0], [0, 1]], [[5, 3, 1, 0], [1,0]]] with open("mydataset.json", "w", encoding="utf-8") as file: json.dump(dataset, file) ... with open("mydataset.json", "r", encoding="utf-8") as file: dataset = json.load(file) |
Стиль
PEP 8 – Style Guide for Python Code дает рекомендации по написанию кода Python, которым соответствуют модули стандартной библиотеки Python. Приоритетными являются читаемость и структурность кода. Впрочем, приведенные рекомендации скорее отражают привычки автора, а не стройную систему, и достаточно спорны:
- длина строк не должна превышать 79 символов для кода и 72 для текста
- для установки начального отступа пробелы предпочтительней табуляции (микс недопустим)
- допустимо минимальное применение разделительных пробелов в выражениях
- пробел допускается в операторах после ,, ;, : и вокруг знаков +, -, =, ==, != в арифметических и логических выражениях, кроме * (почему-то)
- не рекомендуется ни внутри, ни снаружи () и [], кроме случаев предыдущего пункта, но не всегда
- в именах переменных и методов предпочтителен змеиный стиль
- верблюжий стиль применяется в именовании классов
1 |
def example(key: str, value='') -> int: |
Установка Python
Загрузка установочного пакета нужной версии не требует специальных комментариев. Установку следует выполнить в режиме Customize installation, который позволяет выполнить общую установку Python для всех пользователей. Пояснения требуют только две последние опции:
- Download debugging symbols - отладочные символы нужны отладчику смешанного режима в Visual Studio для анализа множества внутренних структур данных
- Download debug binaries - обычно не нужны
Обновление
Для обновления pip:
1 |
python.exe -m pip install --upgrade pip |
Web Server Gateway Interface (WSGI)
WSGI используется для связи со своими веб-серверами многими фреймворками, так делают Django, Flask и многие другие //www.toptal.com
куча
Все ключевые слова Python из !!! :
1 2 3 |
>>> import keyword >>> keyword.kwlist ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] |
Источники
- Python //ru.wikipedia.org
- История языка программирования Python //ru.wikipedia.org
- Devpractice Разработка программного обеспечения, технологии и наука //devpractice.ru
- Python. Уроки .../python-lessons/
- Машинное обучение (ML & DA) .../ml-da/
- Python/Учебник Python 3.9 //ru.wikibooks.org
- Про PYTHON //pythonz.net
- Версии .../versions/
- Работа .../vacancies
- Python //pythonworld.ru
- Введение в Python /сверхкраткий конспект Grigoriy_Alekseev@habr.com (май 2019)
- 10 инструментов Python для работы с изображениями //medium.com
- Как преобразовать файл. npy(numpy) в файл .png //coderoad.ru
- Enviroment
- Python. Строим виртуальное окружение с помощью virtualenv //adw0rd.com (2012)
- Установка интерпретатора Python и среды разрабоки PyDev для Eclipse //adw0rd.com (2009)
- DB
- Python: Работа с базой данных, часть 1/2: Используем DB-API DaneSoul@habr.com (февраль 2017)
- Модуль sqlite — Работаем с базой данных //python-scripts.com
- PRO
- Указатели в Python: в чём суть? Logan Jones@habr.com (Июнь 2019 )
- Введение в RNN Рекуррентные Нейронные Сети для начинающих //python-scripts.com
- Библиотека глубокого обучения Tensorflow spiralis@habr.com (Апр 2017)
- Библиотеки для глубокого обучения: Keras madrugado@habr.com (Апр 2017)
- Рекуррентные нейронные сети (RNN) с Keras stabuev@habr.com (Фев 2020)
- поиск публикаций о библиотеке распознавания голоса CMU Sphinx //habr.com...search
- DSP
- PySDR: A Guide to SDR and DSP using Python by Dr. Marc Lichtman //pysdr.org
- Курс лекций «Основы цифровой обработки сигналов» hukenovs@habr.com (Jul 18, 2019)
- Коротко о работе с RabbitMQ из Python /брокер сообщений протокола AMQP dgusakov@habr.com (Дек 2018)