#!/usr/bin/env python
# coding: utf-8
# # Введение в программирование
# В этой вводной лекции даются ответы на основные вопросы, связанные с процессом программирования: что такое программа, как она создается и выполняется, какие языки программмирования существуют и в чем они отличаются. С некоторыми понятиями из данного раздела вы, вероятно, уже знакомы, однако они приводятся здесь для того, чтобы изложение материала было последовательным и полным. Все примеры программного кода в этом курсе лекций приводятся на языке программирования Python, если не указано иное.
# ## Содержание лекции
# * [Что такое программа?](#Что-такое-программа?)
# * [Языки программирования](#Языки-программирования)
# * [Компиляция и интерпретация](#Компиляция-и-интерпретация)
# * [Вопросы для самоконтроля](#Вопросы-для-самоконтроля)
# ## Что такое программа?
# **Программа** представляет собой последовательность инструкций, которые говорят вычислительной системе, что нужно сделать. Ответственность за выполнение программы лежит на процессоре (CPU), который считывает инструкции одну за другой из оперативной памяти и обрабатывает их. Инструкции, понятные непосредственно процессору, называются **машинными инструкциями** и представляют собой двоичный код строго определенного формата. Вся их совокупность называется **машинным кодом**, при этом, разные модели процессоров могут использовать разные наборы машинных инструкций, т.е. иметь отличающийся машинный код. В качестве примера приведем машинную инструкцию, складывающую два числа для процессора Intel Core i3/i5/i7:
# ```
# 00000001 11000001
# ```
# Можно выделить два очевидных недостатка в программировании непосредственно в машинном коде:
# * крайне длительный и затрудненный процесс программирования - машинные инструкции очень сложно запомнить, и они представляют собой лишь базовые примитивы (вроде простейших арифметических операций с парой чисел), которых требуется написать огромное количество для сколько-нибудь полезной программы
# * программа, написанная в машинных кодах, может быть выполнена только на той модели процессора, для которой она разрабатывалась
# Именно два этих фактора (в особенности первый) привели к созданию языков программирования.
# ## Языки программирования
# **Язык программирования** - это формальный, т.е. описываемый некоторыми правилами, язык, предназначенный для записи компьютерных программ. Все языки программирования можно разделить на **низкоуровневые**, в которых программы мало отличаются от программ в машинных кодах, и **высокоуровневые**, созданные для удобства разработки программ человеком. Несмотря на огромное количество языков программирования высокого уровня, низкоуровневые языки вроде Assembler до сих пор используются в областях, где требуется максимальное быстродействие, так как программы, написанные на них, можно вручную максимально оптимизировать под конкретную модель процессора.
# Подобно обычным языкам, все языки программирования формулируют три составляющих, которые в совокупности определяют, *как* выглядит правильно составленная программа и *что* она делает:
# * **Лексика** - определяет алфавит, из символов которого составляется программа. Как правило это английские буквы в нижнем и верхнем регистрах, цифры, знаки арифметических операций и препинания.
# * **Синтаксис** - описывает допустимые комбинации символов алфавита, которые могут встречаться в правильно составленной программе. Например, `print(1+2)` является программой на языке Python (выводит сумму 1 и 2 на экран), а `print(1+)` нет, потому что согласно правилам этого языка после знака "+" в представленном выражении ожидается еще одно число.
# * **Семантика** - определяет смысл конструкций языка программирования, то есть что они делают. Например, `1+2` в Python означает сумму 1 и 2, однако в другом языке программирования это же выражение может означать что-то другое.
# Как упоминалось выше, основное назначение языков программирования - упростить процесс написания программ. Для этой цели языки программирования максимально приближены к естественным языкам, а это зачастую дает интуитивное понимание смысла программы. В подтверждение этих слов предлагаем вам догадаться самим, что делается в следующей программе (подсказка - после ее выполнения на экран будет выведено некоторое число, но нужно понять, какое именно):
# ```python
# some_list = [10, 5, 13]
# max_value = 0
#
# for value in some_list:
# if value > max_value:
# max_value = value
#
# print(max_value)
# ```
# In[1]:
get_ipython().run_cell_magic('HTML', '', '\nПоказать ответ\n
\n
Программа ищет в списке из трех элементов 10, 5 и 13 наибольший и выводит его на экран. Если вам не удалось ответить правильно, ничего страшного - через несколько лекций этот код покажется вам элементарным.
\n')
# Бывают и такие языки программирования, в которых наоборот сделано все возможное, чтобы программа была нечитабельна, но создаются они исключительно ради эксперимента или шутки. Хорошим примером является язык программирования COW. Вот так выглядит программа, генерирующая [последовательность Фибоначчи](https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%A4%D0%B8%D0%B1%D0%BE%D0%BD%D0%B0%D1%87%D1%87%D0%B8), на этом языке:
#
# ```
# MoO moO MoO mOo MOO OOM MMM moO moO
# MMM mOo mOo moO MMM mOo MMM moO moO
# MOO MOo mOo MoO moO moo mOo mOo moo
# ```
# Итак, мы получили представление о том, как выглядит программа, написанная на некотором языке программирования. Несмотря на большое различие между языками, у них есть одна общая черта: программа на любом из них представляет собой текст, следующий четко определенным правилам языка. Этот текст принято называть **исходным кодом** (или просто кодом) программы.
#
# Как упоминалось ранее, процессор может выполнить только программу, написанную в машинных кодах, поэтому возникает закономерный вопрос: как выполнить программу, написанную на некотором языке программирования, отличном от машинного кода. Ответ на него дается в следующем разделе.
# ## Компиляция и интерпретация
# Существует два основных подхода к выполнению программ:
# * **Компиляция** - перевод программы с языка программирования в машинный код и последующее его выполнение. Компиляция выполняется специальной программой, называемой **компилятором**, которая получает на вход текстовый файл, написанный на некотором языке программирования, и создает из него исполняемый файл, содержащий машинные инструкции, который уже может быть выполнен процессором (в ОС Windows такие файлы имеют расширение _exe_).
# * **Интерпретация** - процесс построчного разбора и выполнения исходного кода программы, выполняемый специальной программой, которая называется **интерпретатором**. Отличие от компиляции заключается в том, что при интерпретации исходный код переводится не в машинный, а в некоторый оптимизированный для быстрой обработки **байт-код**, который исполняется самим интерпретатором, выступающим в роли процессора для программы. При этом интерпретируемая программа выполняется сразу же по мере считывания интерпретатором строк ее исходного кода.
# Как можно заметить, в обоих этих подходах существует этап преобразования программы с языка программирования в программу на некотором другом языке: в случае компиляции другим языком является машинный код, а в случае интерпретации байт-код. Процесс перевода программы, написаннной на одном языке, в программу на другом языке называется **трансляцией**. Специальная программа, выполняющая трансляцию называется **транслятором**.
# Каждый из двух представленных подходов к выполнению программ имеет свои преимущества и недостатки. Главный плюс компиляции в том, что ее можно выполнить один раз, получить исполняемый файл, который можно бесконечное количество раз запускать на процессоре без дополнительной обработки. При интерпретации на каждом запуске программы выполняется ее разбор интерпретатором и трансляция в байт-код, что приводит в общем случае к более медленной работе по сравнению с аналогичной, но скомпилированной программой. С другой стороны, процесс компиляции может занимать очень много времени (исчисляется часами) и должен выполняться при малейшем изменении в исходном коде программы, а интерпретируемая программа запускается мгновенно. Кроме того, интерпретатор может обеспечивать дополнительный уровень безопасности для системы в целом: отслеживать некорректные операции программы, следить за тем, чтобы она не расходовала излишне оперативную память и другое. Обобщенно можно сказать так: компиляция создает более быстрые программы, но требует больше усилий от разработчика, в отличие от интерпретации.
# ![Выполнение программы](./images/01/program-execution.png)
# В соответствии с подходом, используемым для выполнения программ, различают компилируемые и интерпретируемые языки программирования. К числу наиболее известных компилируемых языков относятся C, C++, Objective-C, Go и другие. Python, а также Java, PHP, Perl и другие относятся к интерпретируемым языкам.
# ## Вопросы для самоконтроля
# 1. Что такое программа? Какой компонент компьютера выполняет ее? Как называются инструкции, понятные этому компоненту?
# 2. Как три аспекта обязательно нужно описать, если вы захотите создать свой собственный язык программирования? В чем заключается их суть?
# 3. В чем схожесть и различие компиляции и интерпретации?
# 4. Представьте, что нужно написать программу, обрабатывающую все финансовые транзакции крупного банка. Какой язык программирования предпочтительнее для выполнения этой задачи: компилируемый или интерпретируемый? Почему?
#
# - - -
# [Содержание](00_Overview.ipynb#Содержание) |
# [Следующая: Установка Python](02_Installing_Python.ipynb)