Языки программирования
В этом разделе мы рассмотрим какими они бывают. И снова давайте посмотрим на определение из Википедии:
Python —
высокоуровневый
язык программированияобщего назначения
, ориентированный на повышение производительности разработчика и читаемости кода. Синтаксис ядра Python минималистичен. В то же время стандартная библиотека включает большой объём полезных функций.Python
поддерживаетструктурное
,объектно-ориентированное
,функциональное
,императивное
иаспектно-ориентированное
программирование. Основные архитектурные черты —динамическая типизация
,автоматическое управление памятью
,полная интроспекция
, механизм обработки исключений, поддержка многопоточных вычислений, высокоуровневые структуры данных. Поддерживается разбиение программ на модули, которые, в свою очередь, могут объединяться в пакеты.
Воу Воу Воу! Как много терминов... но давайте мы со всем потихоньку разберется, с тем чем языки программирования отличаются.
ПРЕДУПРЕЖДАЮ! Объяснять я буду своим языком, но и значительно проще чем обычно.
Высокоуровневые/низкоуровневые языки программирования
Высокоуровневые
К высокоуровневым языкам мы можем отнести те, что предоставляют нам высокие абстрации такие как:
- Структуры данных
- Типы
- Классы
- Методы
- Удобное управление памятью
- Методы обработки ошибок
Разрабатывая на высокоуровневом языке, нам не приходится думать про то как наш код исполняется на железе, мы можем писать нашу логику, а интерпретатор/компилятор позаботится об остальном за нас.
Каких- то жестких границ между Высокоуровневыми и низкоуровневыми языками нет, вполне часто язык C
относят к низкоуровневым, так же и Go
python разработчик может отнести к низкоуровневым, вот только с очень большой натяжкой.
В эту группу относят почти все языки с которыми вы могли бы столкнуться на практике. Не частно в наше время люди пишут на языке ассемблера
.
Вводят еще один класс языков -
Сверхвысокоуровневые
, в этот класс относят иPython
.
Низкоуровневые языки программирования
Разрабатывая на низкоуровневых языках, вы пишите код, непосредственно выполняющийся на CPU
, Т.е максимально близкий к железу. Ваши инструкции будут похожи на:
Пример низкоуровневых языков программирования:
- Ассемблер
- Машинный код
Ассемблерный код
- это доступное для понимания человеком представление машинного кода.
Компилируемые и интерпретируемые языки программирования
В языке программирования мы пишем инструкции
, которые в дальнейшем будут исполняться нашей машиной(на CPU
). Есть проблема - CPU
не может понять что мы написали на Python
, для того чтобы привести наши инструкции в машинный
либо байт-код
используется промежуточный инструмент называемый компилятором
.
Компилируемые языки
В абзаце выше вы могли видеть термины машинный код
и байт-код
машинный код
- представляет из себя список команд исполняемый непосредственно процессоромбайт-код
- близкий к машинному код, но он будет интерпретироватьсяинтрерпретатором
иливиртуальной машиной
Для того чтобы лучше понять что такое компиляция
, рассмотрим шаги выполняемые компилятором
:
- Лексический анализ - На этом этапе последовательность символов исходного файла преобразуется в последовательность лексем.
- Синтаксический (грамматический) анализ - Последовательность лексем преобразуется в дерево разбора.
- Семантический анализ - Дерево разбора обрабатывается с целью установления его семантики (смысла) — например, привязка идентификаторов к их декларациям, типам, проверка совместимости, определение типов выражений и т. д. Результат обычно называется «промежуточным представлением/кодом», и может быть дополненным деревом разбора, новым деревом, абстрактным набором команд или чем-то ещё, удобным для дальнейшей обработки.
- Оптимизация Выполняется удаление излишних конструкций и упрощение кода с сохранением его смысла. Оптимизация может быть на разных уровнях и этапах — например, над промежуточным кодом или над конечным машинным кодом.
- Генерация кода Из промежуточного представления порождается код на целевом машинно-ориентированном языке.
Интересной технологией является
JIT-компиляция
. В этом случаеbyte-code
превращается в машинный при надобности,машинный код кешируется
и следующее обращение к нему он уже скомпилирован. Хорошей стороной подобного исполнения программы является то, что мы можем на ходу оптимизировать ее + выгружать ненужный код из оперативной памяти.
Линки
Интерпретируемые языки
Мы уже более-менее имеем представление об компиляторе
, мы поняли, что из компилятора мы можем получить понятный машине
, либо виртуальной машине
код.
Но как вы знаете, вы не компилируете код на Python
, а сразу же его исполняете. Исполнением вашего кода занимается интерпретатор
(скорее всего CPython
). Давайте поверхносто посмотрим на то, как исполняется ваш код на языке Python
интерпретатором CPython
Интерпретатор - Программа исполняющая другие программы. Если говорить упрощенно, то его работа заключается в том, чтобы:
- Загрузить исполняемый файл
- Перевести ваши инструкции в промежуточное представление(
byte-code
) PVM(Python Virtual Machine)
занимается тем, что выполняет комманды изbyte-cod'а
А вот определение из "Лутца":
Интерпретатор – это такой модуль, который исполняет другие программы. Когда вы пишете код на языке Python
, интерпретатор Python
читает вашу программу и выполняет составляющие ее инструкции. По сути дела интерпретатор – это слой программной логики между вашим программ- ным кодом и аппаратурой вашего компьютера.
Разделение языков по парадигмам программирования
Парадигма программирования — это совокупность идей и понятий, определяющих стиль написания компьютерных программ (подход к программированию). Это способ концептуализации, определяющий организацию вычислений и структурирование работы, выполняемой компьютером
И снова скучное определение. Если по простому, то парадигма определяет:
- Как мы пишем код
- Как мы разделяем логику
- Каким образом мы будем манипулировать данными
- В каком виде будем эти данные хранить
Вообще парадигм большое кол-во и они перетекают друг в друга, языки позволяют нам писать в разных парадигмах, и если перечислить парадигмы в которых мы можем писать программы на языке Python
- их будет не один десяток. Мы вообще не пишем с вами в какой-то одной парадигме.
Давайте приведу пример того как мы можем 2 способами отфильтровать список каких-то объектов(в нашем случае котов).
Пример в функциональном стиле
Что мы сделали выше? Отфильтровали список используя только функции, передовая функцию filtrator
как объект в функцию filter
. Подобный подход называется функциональным программированием
. Сущеструют исключительно функциональные языки такие как:
- Lisp
- Erlang
- Elm
Но и, как мы видим, Python
тоже позволяет нам писать в функциональном стиле.
Пример сортировки в императивном стиле
Более привычный стиль написания программы для новичков является процедурный/императивный стиль, в котором мы пишем список инструкций которые будут выполняться последовательно.
Про "последовательно" должен сделать оговорку... мы же видим что некоторые блоки кода выполняются по несколько раз
В примере мы снова отфильтровали котов, но в другом стиле.
Интерактивный пример
Разделение языков по типизации
Фух! Предыдущие абзацы были попроще, но сейчас будет более сложная в понимании теория. Мы поговорим с вами о Системе типов
Система Типов — это совокупность правил, назначающих свойства, именуемые типами, различным конструкциям, составляющим программу. Обычно к конструкциям, нуждающимся в аннотации типов, относятся переменные, поля и свойства объектов, а также параметры и возвращаемые функциями значения.
В основе системы типов любого языка программирования всегда лежит базисная система типов, встроенных в язык. К базисным, или встроенным, типам данных относятся такие типы, как byte
, int
, string
, boolean
, object
и им подобные. На их основе среда выполнения или разработчик могут определять типы данных более высокого уровня, например Date
или Array
.
Типизорованные/нетипизированные языки
Давайте так:
- В
типизированных языках
есть такая абстрация кактип
, и с вероятность 99% вы будете работать именно на таких языках. - Представителями
нетипизированных языков
являетсяЯзык ассемблера
в котором вы манипулируете толькобинарными данными
.
Динамическая/статическая типизация
TODO: Продолжить статью