Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером
Выражения и инструкции
—
Введение в программирование
Видео может быть заблокировано из-за расширений браузера. В статье вы найдете решение этой проблемы.
Транскрипт урока
Взгляните на эту простую строчку кода:
const x = 5;
Вы точно знаете, что в ней происходит, верно? Создадим новую константу x
, зададим ей значение 5. Ничего особенного тут нет.
Вот другая строчка кода:
const y = getAnswer();
Создадим новую константу y
, зададим ей то значение, которое возвращает функция getAnswer
. Теперь представьте, что getAnswer
— это на самом деле невероятно сложная функция с миллионом строчек кода и потребуется 12 лет для её вычисления.
Насколько отличаются эти строчки? Оказывается, в информатике более важный и полезный вопрос: «насколько они схожи?».
И ответ, конечно — «всё относительно».
Если вы рассуждаете о том, что действительно, буквально, происходит — они вообще не похожи друг на друга. Одна устанавливает числовое значение, другая вызывает какую-то функцию. А мы уже хорошо понимаем, что это разные вещи. Мы знакомы с функциями, аргументами и всем, что связано с функциями.
Но иногда полезно оперировать другими понятиями, на другом уровне. Конечно, бегать и управлять самолётом — это очень разные виды активности, но на определённом уровне они подобны — и та и другая подразумевают передвижение из одной точки в другую.
Эти две строчки подобны, потому что справа от знака равно в обоих случаях находится выражение. Выражение — это фрагмент кода, который превращается в значение. Другими словами — становится значением. Да, знаю, 5
— это уже значение, но для интерпретатора JavaScript это выражение, которое превращается в значение 5
. Другое выражение, которое превращается в значение 5
— это, например, 2 + 3
.
Вызов функции getAnswer()
— это тоже выражение, потому что функция что-то возвращает. Этот вызов будет заменён на значение, которое она возвращает. Другими словами, вызов функции превратится в значение, а поэтому он является выражением.
Не всё в коде становится значением. Так что не всё в коде — это выражение, хотя большая часть его — именно выражения.
JavaScript различает выражения и инструкции. Инструкция — это команда, действие. Помните условие с if
, циклы с while
и for
— всё это — инструкции, потому что они только производят и контролируют действия, но не становятся значениями.
Это что, какие-то мутные технические термины из учебников? Может так показаться, но в реальности очень важно понимать и видеть разницу между выражениями и инструкциями.
Это помогает правильно понимать процесс вычисления и выполнения программы. Посмотрите на пример:
12 + square(7 + 5) + square(square(2));
Это выражение состоит из нескольких подвыражений.
Первое — 12
— выражается в 12
. Следующее состоит из множества подвыражений:
7
выражается в7
5
выражается в5
7
+5
выражается в12
square(12)
выражается в144
К этому моменту в процессе JavaScript видит такую картинку:
12 + 144 + square(square(2));
Это еще не конец, остались необработанные выражения. Это будет продолжаться пока всё выражение не превратится в единое значение.
square(square(2))
решается таким способом:
2
выражается в2
square(2)
выражается в4
square(4)
выражается в16
Давайте заглянем в мозг интерпретатора снова:
12 + 144 + 16;
Все внутренние выражения решены, так что теперь сложение происходит в два шага:
12 + 144 + 16;
156 + 16;
172;
Теперь решено всё выражение.
Кстати, оператор сложения имеет левую ассоциативность. Это значит, что в случае с составными сложениями процесс пойдёт слева направо, вот почему мы вначале видим 12 + 144, а потом 156 + 16.
Вы не можете ставить инструкции там, где должны быть выражения. Например, передача инструкции const
как аргумента функции приведёт к ошибке. Как и попытка присвоить инструкцию if
переменной. Подобное просто не имеет смысла в этом языке, потому что в таких случаях предполагаются только выражения:
console.log(const x); // error!
let b = if (x > 10) { return 100; }; // error!
Зная такие вещи, вы скоро обретёте две важные суперспособности:
- Вы будете способны замечать, что большая часть кода, даже та функция из миллиона строк на двенадцать лет, это просто горсть безделушек, которые становятся значениями.
- Вы будете способны замечать, что иногда код просто не будет работать, потому что он не имеет смысла в контексте выражений и инструкций.
Выводы
Выражением (expression) является любой корректный блок кода, который возвращает значение.
Ниже 5
это expression, оно выражается в значение 5
:
const x = 5;
Ниже getAnswer()
— это вызов функции — другое выражение. Этот вызов возвращает значение, то есть этот вызов функции выразится в значение:
const y = getAnswer();
Ниже пример выражения, которое состоит из нескольких подвыражений, и пошаговый процесс превращения каждого выражения по порядку, пока целое выражение не превратится в одно значение:
12 + square(7 + 5) + square(square(2));
12 + square(12) + square(square(2));
12 + 144 + square(square(2));
12 + 144 + square(4);
12 + 144 + 16;
156 + 16;
172;
JavaScript различает выражения (expressions) и инструкции (statements). Инструкция — это (грубо говоря) команда, действие.
if
, while
, for
, const
— примеры инструкций. Они производят или контролируют действия, но не превращаются в значения.
Дополнительные материалы
- Выражения / Mozilla Developer Network
- Приоритет операторов
- Expressions / Mozilla Developer Network
- Expressions versus statements in JavaScript
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
-
130 курсов, 2000+ часов теории -
1000 практических заданий в браузере -
360 000 студентов
Наши выпускники работают в компаниях:
Когда мы готовим блюдо, то четко следуем рецепту. Иначе еда окажется не такой, как ожидали. Это же правило действует и в программировании.
Чтобы увидеть на экране ожидаемый результат, нужно дать компьютеру четкие и пошаговые указания. Это можно сделать с помощью инструкций. Инструкция — это команда для компьютера, единица выполнения. Код на Python в этом случае — это набор инструкций. Его можно представить в виде пошагового рецепта.
Код на Python запускает интерпретатор — программу, которая выполняет инструкции строго по очереди. Как и шаги в рецепте, набор инструкций для интерпретатора пишутся по порядку и отделяются друг от друга переходом на следующую строку.
Разработчики должны понимать порядок действий в коде и уметь мысленно разделять программу на независимые части, удобные для анализа.
Посмотрим на пример кода с двумя инструкциями. При его запуске на экран последовательно выводятся два предложения:
print('Mother of Dragons.')
print('Dracarys!')
# => Mother of Dragons.
# => Dracarys!
Выше мы говорили, что инструкции отделяются друг от друга переходом на новую строку. Но есть и другой способ: их можно разделить точкой с запятой — ;
:
print('Mother of Dragons.'); print('Drakarys!')
Технической разницы между первым и вторым вариантом нет — интерпретатор поймет инструкции одинаково. Разница только в том, что человеку будет неудобно читать второй вариант.
Лучше инструкции располагать друг под другом. Так коллегам будет удобнее читать ваш код, обслуживать его и вносить изменения.
Задание
Выведите на экран друг за другом три имени: Robert, Stannis, Renly. В результате на экране должно отобразиться:
Robert Stannis Renly
Для каждого имени используйте свой собственный вызов print()
.
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя 🤔
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно 🙄
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Полезное
-
Немного об интерпретаторах
Определения
-
Интерпретатор — программа, выполняющая код на Python.
-
Инструкция (statement) — команда для компьютера, написанная на языке программирования. Код на Python — это набор инструкций, разделенных (чаще всего) переводом строки.
Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Выражение(англ. Expression) — инструкция, присваивающая правую часть выражения левой части (выражает левую через правую).
Инструкция ( англ. Statement ) — в программировании, команда языка программирования, которым задается определенный шаг процесса обработки информации на ЭВМ.
1. Любое выражение — это инструкция.
2. Не каждая инструкция — выражение.
Пример кода:
a = 1; выражение
int a = 10; инструкция и выражение (сначала [var a] — инструкция которая не является выражением т.к. присваивания нет, а потом уже [a = 10] — выражение, которое можно также назвать инструкцией).
if (a < 2){} else{} и т.д. — инструкция, но не выражение, ибо ничего не выражается, но действия происходят.
Точно также и с w = x+y+z :
1. x+y+z // инструкция, но не выражение.
2. w = //если вы введете сюда код что вернула инструкция (x+y+z) — выражение и инструкция присваивания одновременно
Блок(англ. Block) — это 0 или больше инструкций помещенных между фигурными скобками и может быть помещен в том месте кода, где это дозволяется. Например:
class BlockDemo {
public static void main(String[] args) {
boolean condition = true;
if (condition) { // начало блока 1
System.out.println("Condition is true.");
} // конец блока 1
else { // начало блока 1
System.out.println("Condition is false.");
} // конец блока 2
}
}
Ссылки на источники:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/expressions.html
http://javascript.ru/forum/misc/25447-raznica-mezhdu-vyrazheniyami-i-instrukciyami.html
Инструкции в Python
Для того, чтобы наша программа могла делать что-то полезное, мы должны предоставить интерпретатору Python верные инструкции, т.е. посредством кода
сообщить ему логическую последовательность действий, выполнение которой и приведет к желаемому результату. Если более строго, то.
Инструкция языка программирования
(от англ. statement) – это команда на языке программирования,
посредством которой компьютеру сообщается о необходимости выполнения одного определенного шага по обработке порции информации.
По сути, любой python-скрипт представляет собой не что иное, как некоторую последовательность инструкций, которая может состоять из десятков, сотен,
тысяч или даже сотен тысяч и миллионов инструкций (см. пример №1). Все зависит от того, сколько инструкций потребуется для того, чтобы описать все шаги,
необходимые для достижения целей программы.
Код
Результат
pythonCodes
# Инструкция импортирует переменную pi из модуля math.
from math import pi
# Позиционное присваивание значений глобальным переменным.
x, y, z = [1, 2, 3]
# Эта инструкция объявляет функцию со значением по умолчанию.
def ex_func(z=0):
# Будут использоваться глобальные переменные.
global x, y
# Комбинированные инструкции присваивания.
# Теперь глобальная x == 10.
x *= 10
# Теперь глобальная y == 20.
y += 18
# Глобальная z не изменилась, а локальная z == z*z.
z **= 2
# Инструкция объявляет вложенную функцию.
def in_func():
# Будет использоваться переменная z из области видимости
# объемлющей функции, т.е. ex_func.
nonlocal z
# Инструкция запускает цикл.
for i in range(25):
# Условная инструкция.
if i<5:
# Инструкция перехода в начало цикла.
continue
# От 5 до 9.
elif i>=5 and i<10:
# Увеличиваем z из обл. видимости ex_func.
z += i
# При i == 10.
else:
# Инструкция прерывания цикла.
break
# Инструкция возврата значения функцией in_func.
return z
# Инструкция возврата значения функцией ex_func.
return x + y + in_func()
# Инструкция будет отлавливать и обрабатывать исключения.
try:
# Инструкция присваивает переменной рез-т вычисления выражения.
res = int(pi)*10 + ex_func(30) + int(input('Введите число: '))
# Инструкция выводит результат на экран.
print(res, end='\n\n')
# Блок выполняется, когда возбуждается исключение.
except Exception as err:
# Выводим сообщение об ошибке.
print(err)
# Если ошибок нет.
else:
# Ничего не делаем (пустая инструкция-заполнитель).
pass
# Этот блок выполняется всегда, даже при наличии исключения.
finally:
# Запрашиваем ввод, чтобы окно не закрылось.
input()
Введите число: число
invalid literal for int() with base 10: 'число'
Пример №1. Виды и формы инструкций в Python.
Как видим, к инструкциям можно отнести практически все команды, которые мы пишем в коде программы: импорт модулей, присваивание или удаление ссылок на объекты, определение функций,
циклы, условные конструкции, обработка исключений и т.д. При этом, в случае необходимости, все эти инструкции могут быть объединены посредством отступов в целые блоки инструкций, каждый из
которых может содержать собственные вложенные блоки инструкций (в нашем примере уровень вложенности достигает четырех).
В последующих параграфах мы обязательно рассмотрим все виды инструкций и их особенности более подробно. Сейчас же, для более полного представления о наборе инструкций, использующихся в
Python, мы просто перечислим основные из них, дав краткие пояснения (в процессе чтения обязательно еще раз посматривайте в пример
№1).
-
a = b – это инструкция присваивания (например, a = 5**2 — 3 или
b = len([1, 2, 3])). Помимо этого имеются и другие формы присваивания: комбинированные инструкции присваивания (например,
a += 5 или b **= 7), позиционное присваивание (например, a, b = 5, 7 или
[a, b] = ‘AB’), операция распаковывания последовательностей (например, a, *b = 1, 2, 3 или
a, *b, c = ‘ABCDEF’), а также групповое присваивание одного значения (например, a = b = c = 5). Алгоритм присваивания
у всех этих форм несколько отличается, но главная цель у них одна – это создание ссылок на объекты и сохранение их в переменных. При этом стоит добавить, что присваивание может
быть и неявным, например, в вызовах функций или в заголовках циклов, но в любом случае результатом будут ссылки на объекты, сохраненные в переменных. -
def – определение функций и методов. Например,
def my_func(a, b, c=0, *d): return a + b + c + d[0]. - return – возврат результата из функций и методов.
-
yield – инструкция возврата результата из функции-генератора с сохранением состояния ее
локальных переменных. При повторном вызове такой функции выполнение, в отличие от инструкции return, продолжается с ключевого слова
yield, на котором ее работа была прервана ранее. - class – определение классов. Например, class MyСlass: pass.
- pass – пустая инструкция-заполнитель.
-
global – инструкция объявления используемых переменных глобальными (если переменных несколько, то они
перечисляются через запятую). -
nonlocal – инструкция используется во вложенных функциях и объявляет переменные нелокальными. В результате
интерпретатор будет использовать переменные с указанными именами из ближайшей области видимости (т.е. объемлющей функции), исключая глобальную. - if/elif/else – условная инструкция.
- for/else – инструкция обхода последовательности в цикле.
- while/else – цикл общего назначения.
- break – инструкция выхода из цикла.
- continue – инструкция перехода в начало цикла.
-
import – инструкция импорта всех доступных имен из указанных модулей (модули
присваиваются по одному за одну инструкцию, хотя допускается и по несколько за раз, но тогда они перечисляются через запятую). -
from/import – инструкция импорта из модуля только указанных имен
(имена перечисляются через запятую). Например, from math import pi as p, tau as t. - try/except/finally – инструкция обработки исключений.
- raise – инструкция возбуждения исключений.
-
assert – инструкция отладки, которая позволяет производить проверку
истинности утверждений и выводить сообщение об ошибке. Например, assert x > y, ‘Значение x недопустимо мало!’. - with/as – менеджер контекста.
-
del – инструкция удаления ссылок на объекты (если ссылок несколько, то они перечисляются через запятую). Например,
del a, b[0], c[‘car’] .
Отметим, что список инструкций языка Python постоянно изменяется. Происходит это не сразу, но после выхода очередных версий языка регулярно появляются новые
виды инструкций, а некоторые старые виды постепенно обновляются или вообще удаляются.
Что касается вызовов функций, генераторов и других выражений, то они тоже являются инструкциями, но при этом их выделяются в особую группу за счет следующих особенностей:
-
могут объединяться операторами в сколь угодно длинные конструкции, которые в итоге последовательных операций вычисляются интерпретатором и возвращаются в виде одного
единственного значения (объекта некоторого типа); - могут использоваться внутри других инструкций, являясь их составной частью.
Например, инструкция присваивания res = 5 + my_func(1, 2) содержит в правой части выражение, включающее вызов функции. Однако в
результате вычислений в переменной сохранится ссылка лишь на один итоговый объект.
В отличие от выражений обычные инструкции в Python не могут использоваться там, где ожидается значение. Поэтому их нельзя использовать в качестве
аргументов функций, правой части присваиваний, в качестве операций или возвращаемых значений. Например, если в инструкции выше заменить вызов функции ее определением в виде
res = 5 + (def my_func(a, b): return a + b), интерпретатор возбудит исключение.
По умолчанию интерпретатор Python выполняет инструкции последовательно одна за другой в порядке их следования в коде. Однако ряд специальных
инструкций, называемых управляющими конструкциями, позволяют изменять ход выполнения программы по умолчанию. К ним
относятся:
-
условные инструкции, такие как if/else или
if/elif/else, которые указывают интерпретатору Python на выполнение или пропуск других
инструкций в зависимости от значения условного выражения; -
инструкции циклов, такие как for/in или
while, которые указывают интерпретатору на многократное выполнение других инструкций; -
инструкции переходов, такие как break,
continue или return, которые указывают интерпретатору на выполнение перехода в другую
часть программы; -
инструкции обработки исключений, такие как try/except/else
или try/except/finally, которые указывают интерпретатору на выполнение перехода в другую часть программы в случае возникновения
ошибок.
Выражения в Python
Выражения являются не менее важными строительными элементами в Python, чем другие инструкции. Ведь большая часть того, что пишется в коде, является
выражениями.
Выражение (от
англ. expression) – это любая единица исходного кода Python,
которая может быть вычислена интерпретатором для получения значения. При этом литералы и переменные считаются выражениями сами по себе, а вызовы функций и некоторые другие конструкции
вроде генераторов следует относить к выражениям из-за того, что они явно или неявно, но дают результат.
Выражения делятся на простые (первичные) и сложные. Простые выражения не могут быть разделены на еще более простые выражения. К ним относятся, например, литералы, инициализированные
переменные, вызовы функций. Сложные выражения составляются из более простых при помощи различных операторов, которые позволяют выполнять такие операции, как сложение, вычитание,
конкатенация и другие (см. пример №2).
Код
Результат
pythonCodes
# Присваивается смешанное выражение, включающее
# генератор списка, арифметические выражения,
# выражения сравнения и логическое выражение.
li = [x*10 for x in (0, 1, 2, 3) if x > 0 and x != 3]
# Анонимная функция и ее вызов в арифметическом выражении.
res = (lambda a, b: a + b)(li[0], li[1])**2
# Выражения с операторами идентичности и членства,
# выражения вызовов функций.
if res in [900, 1000] and type(res) is int:
print(res)
900
Пример №2. Использование выражений в Python.
В примере выше простые выражения литерального значения (например, 10, (0, 1, 2, 3), int),
выражения переменных (например, x или res) и выражения вызовов функций (например,
type(res) или более сложный вызов анонимной функции (lambda a, b: a + b)(li[0], li[1])) посредством операторов объединяются
в более длинные смешанные выражения. Однако все эти примеры далеко не предел, т.к. выражения могут использоваться везде, где интерпретатор ожидает получить значение. Да, порой выражения могут
выглядеть довольно длинными и сложными, но в результате вычислений на выходе интерпретатор все равно будет оперировать каким-то одним результирующим значением.
Опять же, в последующих параграфах мы обязательно рассмотрим все виды выражений и особенности их использования более подробно. Сейчас же, просто перечислим основные из них для
ознакомления, дав краткие пояснения (в процессе чтения обязательно еще раз посматривайте в пример №2).
-
Выражения литерального значения – это литералы в коде программы, например, ‘ten’ (строка),
10 (число), [‘ten’, 10] (список) или list (объект). -
Выражения переменных – обычные инициализированные переменные, например, res в выражении
res in [900, 1000] (здесь переменная уже инициализирована, а значит обращение к ней возвращает значение, сохраненное в памяти под данным именем). - Арифметические выражения – используются привычные нам математические операторы, например, a + b**3.
- Условные выражения или выражения сравнения – используются операторы сравнения, например, a <= b.
- Выражения с логическими операторами – используются логические операторы, например, a > b and a < c.
- Выражения с побитовыми операторами – используются побитовые операторы, например, a&b.
-
Выражения с операторами принадлежности – используются операторы принадлежности (членства) in и
not in, например, 5 in [1, 2, 3]. -
Выражения с операторами идентичности – используются операторы идентичности is и
is not, например, 5 is not ‘5’. - Вызовы функций и методов – это тоже выражения, т.к. они явно или неявно возвращают результат, например, f(3, 5).
-
Генераторы – генераторы выражений, списков, словарей, множеств. Например,
{simb for simb in ‘123’}. -
lambda-выражения или анонимные функции – это специальные конструкции, которые позволяют встраивать определения функций в программный код
выражений. Например, 5**2 + (lambda x, y: x — y)(5, 2). -
Выражения присваивания – используется моржовый оператор
:=, который позволяет присваивать значения непосредственно в выражении. Например, x = 5 + (y:=5). -
Трехместные выражения if/else – эти конструкции позволяют использовать в выражениях
условную инструкцию if/else в ее простейшей форме. Например, x = True if y > 0 else False.
Да, разделение по категориям получилось несколько условным, но вполне наглядным для того, чтобы отличать в коде выражения от инструкций. Это внешне. Логически выражения также несколько
отличаются по своему использованию и смысловому содержанию. Ведь выражения – это все, что состоит из объектов (ну, или ссылок на них) и операторов и может быть вычислено интерпретатором
для получения значения, а инструкции – это указания на выполнение программой каких-либо действий (необязательно вычислений). Да, выражения вполне обоснованно можно считать особым видом
инструкций, результатом исполнения которых являются значения. Но при этом не стоит забывать, что на практике выражения практически всегда входят в состав каких-либо инструкций и других более
сложных смешанных выражений, а вот использование инструкций в выражениях недопустимо (например, инструкция d = 5 + (def my_func(): return 3) однозначно вызовет
сбой скрипта).
Операторы в Python
Как было сказано выше, для составления более сложных выражений используются операторы, которые позволяют выполнять над объектами этих выражений некоторые операции. Но
что мы имеем в виду, когда говорим, что хотим выполнить над объектами некоторую операцию при помощи соответствующего оператора?
Операции (от
англ. operations) – это те действия, которые мы выполняем над переменными и объектами.
Некоторые операции нам уже известны (например, сложение, умножение, присваивание или сравнение), знакомство с другими еще только предстоит. Но в любом случае, чтобы
интерпретатор понял, какую операцию над объектами мы хотим выполнить, нужно использовать не слова, а соответствующие им операторы.
Операторы (от
англ. operators) – это элементы программного кода, которые используются для указаний
программе на выполнение определенных действий в выражении. Проще говоря, операторы – это символьные обозначения команд, с помощью которых мы выполняем операции.
Примерами выражений с использованием операторов могут служить
a + b, a != b, -b,
a > b, (b + 7)/(5 — 3**2) и др. Здесь символы и комбинации символов
+, !=, **, —,
/, > и есть операторы. Кстати, выражения или значения, расположенные по сторонам операторов,
называют операндами.
Большинство операторов обрабатывают свои операнды в определенном направлении. Это свойство принято называть ассоциативностью. Одни
операторы выполняют обработку своих операндов слева направо, обладая левой ассоциативностью, другие обладают правой ассоциативностью, выполняя обработку в обратном
направлении, т.е. справа налево. Также существуют операторы не имеющие ассоциативности.
Кроме того, операторы могут отличаться своим приоритетом, который определяет порядок (очередность) их выполнения в ходе вычисления
значения выражения. Первыми обрабатываются операторы с более высоким приоритетом, затем операторы с более низким приоритетом и так далее по мере убывания их приоритетности.
Если приоритет операторов одинаков, они группируются и обрабатываются либо согласно их ассоциативности, либо в соответствии с установленным для них порядком (это
касается операторов, у которых ассоциативность отсутствует). Также отметим, что для принудительного указания порядка выполнения операторов используются круглые скобки
(см. пример №3).
Код
Результат
pythonCodes
# Теперь a==19, т.к. приоритет оператора * выше, чем у +.
a = 5 + 7*2
print('5 + 7*2 ->', a)
# Теперь b==24, т.к. порядок был указан при помощи скобок.
b = (5 + 7)*2
print('(5 + 7)*2 ->', b, end='\n\n')
c = 2
# Вернет True, т.к. согласно принятому порядку
# это тоже самое, что и a < b and b > c.
print(a < b > c)
# Вернет False, т.к. скобки явно указывают порядок выполнения.
print('a < (b > c) ->', a < (b > c), end='\n\n')
# Согласно принятому порядку это тоже самое, что и c = (a = b).
# А вот использование инструкции c = a += b вызовет ошибку.
c = a = b
# Теперь d == -8, т.к. операторы - и - имеют равный приоритет и
# левую ассоциативность, поэтому 5 - 6 - 7 == (5 - 6) - 7.
d = 5 - 6 - 7
print('5 - 6 - 7 ->', d, end='\n\n')
# Теперь d == 1, т.к. (0 and 0 or 1) == (0 and 0) or 1.
d = 0 and 0 or 1
print('0 and 0 or 1 ->', d)
# Теперь d == 0, т.к. операция в скобках выполняется первой.
d = 0 and (0 or 1)
print('0 and (0 or 1) ->', d)
5 + 7*2 -> 19
(5 + 7)*2 -> 24
True
a < (b > c) -> False
5 - 6 - 7 -> -8
0 and 0 or 1 -> 1
0 and (1 or 0) -> 0
Пример №3. Использование операторов в Python.
Для большей наглядности мы перечислили основные операторы языка Python, использующиеся в выражениях, в порядке убывания их приоритетов
в таблице №4. Чем ниже приоритет, тем ниже находится строка с соответствующими операторами. Если операторы имеют одинаковый приоритет,
они перечисляются в одной и той же строке таблицы.
Оператор | Описание | Ассоциативность |
---|---|---|
** | Возведение в степень | Справа налево |
~ + — |
Побитовое отрицание (инверсия битов) Унарный плюс Унарный минус |
Справа налево |
* / % // |
Умножение Деление Деление по модулю Целочисленное деление |
Слева направо |
+ — |
Сложение Вычитание |
Слева направо |
<< >> |
Побитовый сдвиг влево Побитовый сдвиг вправо |
Слева направо |
& | Побитовое and (И) | Слева направо |
^ | Побитовое xor (исключающее ИЛИ) | Слева направо |
| | Побитовое or (ИЛИ) | Слева направо |
< <= > >= == != is, is not in, not in |
Меньше Меньше или равно Больше Больше или равно Равно Не равно Операторы тождественности Операторы членства |
Отсутствует |
not | Логическое отрицание (НЕ) | Справа налево |
and | Логическое И | Слева направо |
or | Логическое ИЛИ | Слева направо |
:= | Моржовый оператор (выражение присваивания) | Справа налево |
Таблица №4. Основные операторы языка Python.
Старайтесь всегда использовать скобки, непосредственно определяя порядок группировки и не полагаясь на приоритет или ассоциативность операторов, поскольку это
облегчит сопровождение кода и поиск ошибок как при наличии сложных выражений, так и в случае изменения поведения операторов при переходе от одной версии
Python к другой.
Большинство операторов, приведенных в таблице, являются бинарными, т.е. используются с двумя операндами (например,
+, —, !=). Есть также операторы, которые
работают только с одним операндом, их называют унарными. Примером может служить —
(оператор отрицания или унарный минус), который применяется для смены знака числа на противоположный.
В конце параграфа хотелось бы еще раз отметить, что фрагменты кода с присваиванием значений переменным в Python принято
считать инструкциями присваивания. Это связано с тем, что такие фрагменты внутри обычных выражений не разрешены, а в документации все операторы присваивания
объединены в одну группу и перечислены в отдельном пункте 2.6 «Delimiters» вместе
с другими разделителями (хотя и с оговоркой, что они могут выступать в роли операторов). Например, фрагменты кода d = 5,
s += 7**2 или li[0] += 3 — f мы будем называть инструкциями присваивания. Тем не
менее одна форма выражения присваивания в языке все таки имеется. Формируется она при помощи недавно введенного моржового оператора
:=, который может использоваться не только в инструкциях, но и внутри обычных выражений. Например, инструкция присваивания
li = [a := 1, b := 2] включает также и два выражения присваивания.
Краткие итоги параграфа
-
Инструкции – это команды на языке Python, которые сообщают интерпретатору последовательность
действий, необходимых для достижения поставленных целей. По умолчанию интерпретатор выполняет инструкции последовательно одна за другой в порядке их следования
в коде. Если нужно изменить выполнение хода программы по умолчанию, используются управляющие конструкции: условные инструкции, циклы, инструкции переходов или
инструкции обработки исключений. -
Выражение – это любая единица исходного кода Python, которая может быть вычислена
интерпретатором для получения значения. Сложные выражения составляются из более простых при помощи различных операторов, которые позволяют выполнять над объектами
такие операции как сложение, вычитание, сравнение и т.д. Но каким бы сложным не было выражение, в результате последовательных вычислений на выходе интерпретатор
все равно будет оперировать каким-то одним результирующим значением. -
Важно помнить, что на практике выражения практически всегда входят в состав каких-либо инструкций, а вот использование последних в выражениях недопустимо
(например, попытка выполнения инструкции d = if 3>k: k=3 приведет к ошибке). -
Операторы представляют собой символьные обозначения команд, с помощью которых мы выполняем операции над объектами. Выражения или значения, расположенные по сторонам
операторов, называют операндами. Если оператор используется с двумя операндами, его называют бинарным. Если же оператор работает только с одним операндом, его
называют унарным. Так в выражении -3 + (2 — 5)*7 операторы + и *
представляют собой бинарные операторы, а вот оператор — используется и как бинарный оператор вычитания, и как унарный минус. -
Большинство операторов обрабатывают свои операнды в определенном направлении. Это свойство принято называть ассоциативностью. Одни операторы выполняют обработку
своих операндов слева направо, обладая левой ассоциативностью, другие обладают правой ассоциативностью, выполняя обработку в обратном направлении, т.е. справа налево.
Кроме того, существуют операторы не имеющие ассоциативности. Так левой ассоциативностью, в основном обладают бинарные операторы, правая ассоциативность
присуща унарным операторам, а операторы сравнения вообще не обладают ассоциативностью. -
Важным является и приоритет операторов, т.к. операторы с большим приоритетом обрабатываются первыми. Например, значением выражения
2*7 + 4 будет 18, а не 22, т.к. приоритет оператора умножения
выше приоритета оператора сложения. -
Если приоритет операторов одинаков, они группируются и обрабатываются либо согласно их ассоциативности, либо в соответствии с установленным для них порядком (это
касается операторов, у которых ассоциативность отсутствует). В любом случае лучше всегда использовать скобки, непосредственно определяя порядок группировки и не
полагаясь на приоритет или ассоциативность операторов.
Вопросы и задания для самоконтроля
1. Что такое инструкция? А что такое выражение? Можно ли считать любое выражение инструкцией и наоборот?
Показать решение.
Ответ. Инструкция в Python – это команда интерпретатору на выполнение
какого-либо действия по обработке порции информации. А выражение – это любая единица исходного кода Python, которая может
быть вычислена интерпретатором для получения значения.
В принципе любое выражение можно считать особым видом инструкций, которые указывают интерпретатору на вычисление какого-либо фрагмента кода и в результате выполнения
приводят к какому-то значению. Но не любая инструкция может считаться выражением, т.к. инструкции могут указывать не только на вычисления, но и, например, на простой
переход в другую часть программы или выполнение кода определенное число раз. Более того, в Python инструкции могут содержать выражения,
а вот использовать инструкции в составе выражений нельзя (если, конечно, инструкция сама не является выражением).
2. Какие из представленных фрагментов кода относятся к инструкциям, а какие к выражениям:
2**3 + my_func(a),
if a > 2**3: print(a),
s = 2**3,
a < 2**3 and a > 5? Будем считать, что переменные уже инициализированны, а функция определена.
Показать решение.
Ответ. if a > 2**3: print(a) – условная инструкция, хотя в ней и
содержится выражение a > 2**3; s = 2**3 – инструкция присваивания;
2**3 + my_func(a) и a < 2**3 and a > 5 – выражения, т.к. оба фрагмента кода
содержат только операторы и объекты и могут быть вычислены.
3. Какие значения будут присвоены переменным в результате вычисления выражений
a = 5 + 10*5,
b = 5/10*5,
a = True in [True] is True? Выведите их на экран.
Показать решение.
Решение
Результат
pythonCodes
# Приоритет оператора умножения выше.
# 5 + 10*5 == 5 + (10*5).
a = 5+10*5
# Выведет 55.
print('5 + 10*5 =', a, end='\n\n')
# Приоритет одинаков, ассоциативность левая.
# 5/10*5 == (5/10)*5.
b = 5/10*5
# Выведет 2.5.
print('5/10*5 =', b, end='\n\n')
# Приоритет оператора is выше.
# True in [True] is True == True in ([True] is True).
res = True in [True] is True
# Выведет False.
print('True in [True] is True ->', res)
5 + 10*5 = 55
5/10*5 = 2.5
True in [True] is True -> False
4. Какие из представленных фрагментов кода содержат ошибки:
a = 7 *= 3,
c = [8, (b = True) or (g = False)],
a = 7 + (b = 5*2),
a = 7 + (b := 5*2)? Объясните ответ.
Показать решение.
Ответ. Все фрагменты кода, кроме последнего, содержат ошибки, т.к. использование инструкций присваивания внутри
обычных выражений недопустимо. А вот в состав последнего примера входит именно выражение присваивания, поскольку вместо обычного оператора присваивания был
использован моржовый оператор присваивания :=.
Быстрый переход к другим страницам
слова const. Это обусловлено тем обстоятельством, что при использовании этого способа работает аппарат контроля типов.
Имеется один недостаток, связанный с использование определения символических констант с помощью зарезервированного слова const. Дело в том, что символическую константу, определенную таким образом нельзя использовать при определении размера массивов. В этом случае можно воспользоваться константами перечисления (массивы будут рассматриваться во второй части пособия).
При программировании на языке Си необходимо различать следующие программные элементы:
●операторы,
●выражения,
●инструкции.
Операторы (operators) предназначены для выполнения некоторых элементарных действий. Например, в языке Си имеется оператор сложения ( + ), предназначенный для сложения двух чисел.
Выражение (expression) – конструкция языка, используемая для вычисления одного значения или (и) достижения побочного эффекта (side effect). О побочных эффектах при вычислении выражений см. п. 1.14.3. Выражения строятся из операндов, операторов и круглых скобок. В качестве операндов могут выступать константы, переменные, вызовы функций и выражения в круглых скобках. Литерал и переменную можно рассматривать как частный случай выражения. Пусть, например, имеется следующая синтаксическая конструкция:
3 + 5
Это пример простейшего выражения, в котором используется упоминавшийся выше оператор сложения.
Инструкция (statement) – это отдельное предложение языка Си, предписывающее компилятору выполнить некоторые действия. К числу инструкций относятся такие управляющие конструкции, как if, for и т. д. Важно отметить, что в языке Си имеется тесная связь между выражениями и инструкциями. Дело в том, что любое выражение, после которого поставлена точка с запятой, становится инструкцией. Такой вид инструкции называется инструкцией – выражением. Приведем пример. Пусть a, b и y – переменные типа double. Тогда следующая синтаксическая конструкция является выражением:
y = a * b
В этом выражении используются два оператора. Первым из них является оператор присваивания (=), а вторым — оператор умножения (*). Если теперь в конце этого выражения поставить точку с запятой, то получим инструкцию присваивания:
y = a * b;
23
В настоящем разделе основное внимание будет уделено операторам и выражениям.
14.1. Классификация операторов
Операторы языка Си делятся на три категории:
●унарные,
●бинарные,
●тернарные.
Воснову этой классификации положено количество операндов, с которыми работает оператор. Унарные операторы имеют только один операнд, бинарные операторы работают с двумя операндами и у единственного в языке Си тернарного оператора – три операнда (? :). Например:
●-a (выражение содержит унарный минус),
●a – b (выражение содержит бинарный минус),
●a > b ? a : b (выражение содержит тернарный оператор).
14.2.Приоритет и ассоциативность операторов.
Важнейшими характеристиками операторов являются их приоритет и ассоциативность. Использование этих характеристик позволяет определить смысл выражения. Если отсутствуют скобки, то операнды сильнее связываются с операторами, имеющими более высокий приоритет. Можно говорить о том, что операторы с более высоким уровнем приоритета сильнее “притягивают” операнды. Если два оператора имеют одинаковый приоритет, то связывание определяется ассоциативностью. Имеются две разновидности ассоциативности операторов: левосторонняя и правосторонняя. При левосторонней ассоциативности процесс связывания начинается слева, а при правосторонней ассоциативности – справа. Приоритет и ассоциативность позволяют выполнить группировку операторов и операндов в выражении, содержащем более одного оператора.
Приоритеты операторов языка Си и их ассоциативность представлены в таблице, приведенной ниже.
Приоритет |
Название оператора |
Знак |
Ассоциативность |
операции |
|||
Функция |
|||
() |
|||
Индексирование |
[] |
||
1 |
Селектор поля структуры |
-> |
Левосторонняя |
(высший) |
Селектор поля структуры |
. |
|
Инкремент постфиксный |
++ |
||
Декремент постфиксный |
— |
||
2 |
Логическое отрицание |
! |
Правосторонняя |
Побитовое отрицание |
~ |
||
Инкремент префиксный |
++ |
24
3
4
5
6
7
8
9
10
11
12
13
14
15
(низший)
Декремент префиксный Унарное сложение Унарное вычитание Разыменование Взятие адреса Приведение типа Размер объекта Умножение Деление
Вычисление остатка деления Сложение бинарное
Вычитание бинарное Сдвиг влево Сдвиг вправо Меньше Неменьше Больше Небольше
Сравнение на равенство Сравнение на неравенство Побитовое И Побитовое исключающее ИЛИ Побитовое ИЛИ Логическое И
Логическое ИЛИ Вычисление выражения по условию
Присваивания:
Запятая
—
+
—
*
&
(тип) sizeof
*
/
%
+
—
<<
>>
<
>=
>
<=
==
!=
&
^
|
&&
||
?:
= += -= *= /= %= >>= <<= &= ^= &= ^= |=
,
Левосторонняя
Правосторонняя
Левосторонняя
В таблице операторы, имеющие одинаковый приоритет, объединены в группы. За каждой группой операторов закреплен номер, определяющий ее приоритет. Наибольший приоритет (1) имеет группа, расположенная вначале таблицы, а наименьший (15) – имеет оператор “запятая”, который находится в конце таблицы.
Приведем примеры выражений, при вычислении которых необходимо учитывать приоритет и ассоциативность операторов.
Пример 1. Рассмотрим следующее выражение:
25
a + b * c
В этом выражении используются два оператора: + (сложить) и * (умножить). Оператор умножить имеет более высокий приоритет по сравнению с оператором сложить. Это следует из таблицы приоритетов, приведенных выше. В рассматриваемом примере вначале будет выполнено умножение переменных b и c, а затем — сложение полученного результата со значением переменной a и полученное значение станет значением всего рассматриваемого выражения.
Пример 2. Рассмотрим выражение, в котором операторы имеют одинаковый приоритет:
a * b / c
Операторы * и / (делить) имеют одинаковый приоритет. В этом случае следует учитывать ассоциативность операторов. Обратившись к таблице, приведенной выше, находим, что операторы * и / имеют одинаковый приоритет и являются левоассоциативными. При левосторонней ассоциативности операторы выполняются в порядке их следования слева направо. Поэтому вначале будет выполнено умножение, а затем деление.
14.3.Побочные эффекты и вычисления выражений
Следует учитывать, что при вычислении выражений языка Си возможно появление побочных эффектов. Побочные эффекты могут иметь различную природу. Например, имеются операторы языка Си (присваивание, инкремент и декремент), при выполнении которых изменяется значение операнда. Побочные эффекты могут иметь место при выполнении вызовов функций.
Обратимся к приведенной выше инструкции присваивания
y = a * b;
Побочный эффект здесь состоит в изменении операнда “y”, которому присваивается новое значение, равное значению выражения a * b.
Результат вычислений, предусмотренный выражением, может использоваться двумя способами:
●в виде значения выражения,
●с помощью побочного эффекта.
Основным способом является использование значения выражения. В процессе выполнения программы выражение замещается вычисленным значением.
Операторы инкремента и декремента рассматриваются в п. 1.15.1. Там же обсуждаются и побочные эффекты при их выполнении.
Функции языка Си имеют много общего с математическими функциями. Существенное отличие функций языка Си от математических функций состоит в том, что их выполнение может сопровождаться появлением побочных эффектов. В этом отношении язык Си не является уникальным. Побочные эффекты имеют место при работе функций многих языков программирования.
Перейдем к выяснению существа рассматриваемой проблемы. Пусть имеется некоторая произвольная математическая функция y = f(x).
26
Многократные вычисления этой функции для фиксированного значение аргумента x дают всегда один и тот же результат. Причем на этот результат не влияют вычисления других математических функций. Иначе обстоит дело при использовании функций языка Си. Для иллюстрации сказанного приведем пример, в котором используются две библиотечные функции: srand() и rand(), прототипы которых имеют следующий вид:
#include<stdlib.h>
void srand(unsigned seed);
int rand(void);
Функции srand() и rand() применяются для получения так называемой псевдослучайной последовательности чисел. Функция rand() выполняет основную работу по формированию такой последовательности. Для получения последовательности, состоящей из n чисел, необходимо n раз вызвать эту функцию. Функцию srand() следует предварительно вызвать для формирования каждой новой последовательности псевдослучайных чисел. Вызов этой функции используется для инициализации генератора псевдослучайных чисел. Инициализация генератора одним и тем же значением аргумента функции srand() приводит к созданию идентичных псевдослучайных последовательностей. Последовательность чисел, сгенерированная функцией rand() без инициализации генератора, идентична полученной при инициализации с помощью функции srand() со значением аргумента, равным 1. Ниже приведен программный код, с помощью которого формируются две числовые последовательности, состоящие каждая из трех чисел.
srand(10);
printf(«%-20s%5d», «The first series: «, rand() % 100); printf(«%5d», rand() % 100);
printf(«%5d\n», rand() % 100); srand(50);
printf(«%-20s%5d», «The second series: «, rand() % 100); printf(«%5d», rand() % 100);
printf(«%5d\n», rand() % 100);
Замечание 1. В выражении rand() % 100 используется оператор “вычисления остатка” от деления, использующий знак %. Этот оператор вычисляет остаток от деления левого операнда на правый.
Замечание 2. Текстовые литералы: “The first series ” и “The second series” выводятся с использованием выравнивания по левой границе отведенного для каждого поля шириной в 20 позиций. Для этого в спецификации им соответствующей используется модификатор минус (-). При выводе чисел используется принятое по умолчанию выравнивание по правой границе поля.
В результате выполнения этого фрагмента кода в системе
программирования |
Dev |
C++ |
version |
4 |
были получены две |
последовательности псевдослучайных чисел: |
|||||
The first series: |
72 |
99 |
71 |
||
The second series: |
1 |
51 |
10 |
27
Соседние файлы в папке 1сем Дагаев
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #