Готовый перевод How to Think Like a Computer Scientist: Learning with Python 2nd Edition. / Как стать программистом: учимся вместе с Python. Второе издание.: Chapter 4 Conditionals

Внимание! Этот перевод, возможно, ещё не готов, так как модераторы установили для него статус «идёт перевод»

4 Условные выражения

4.2 Оператор остатка

Оператор остатка работает с целыми числами (с целочисленными выражениями) и дает остаток от деления первого числа на второе. В python оперетор остатка обозначается знаком процента (%). Синтаксис такой же, как и у других операторов:

>>> quotient = 7 / 3
>>> print quotient
2
>>> remainder = 7 % 3
>>> print remainder
1

Так 7 разделить на 3 равно 2, в остатке 1.

Операция остатка от деления имеет несколько полезных свойств. Например, вы можете проверить делится ли одно число на другое без остатка; если остаток равен нулю, значит делиться.

Так же можно возвращать правые цифры из числа. Например, x%10 вернет одну саму правую цифру, x%100 вернет две правых цифры.

4.2 Логические (булевы) значения и выражения

Тип в python для храниния значений True "Правда" и False "Ложь" называется булевым, в честь английского математика Джоджа Буля. Джордж Буль создал булеву алгебру, которая является основой для всей современной компьютерной арифметики.

Есть только два булевых значения: True "Истина" и False "Ложь". Запись с большой буквы важна; так, true и false не являются булевыми значениями.

>>> type(True)
<type 'bool'>
>>> type(true)
Traceback (most recent call last): File "<stdin>", line 1, in <module>
NameError: name 'true' is not defined

Булево выражение - это выражение, результатом которого является булево значение. Оператор == сравнивает два значения и выдает булево значение:

>>> 5 == 5
True
>>> 5 == 6
False

В первой операции два числа являются эквивалентными, так что выражение возвращает истину -True; во второй операции 5 не эквивалентно 6, поэтому на выходе мы получаем ложь - False.

Оператор == - это один из операторов сравнения, другие операторы:

x != y # x не эквивалентно y
x > y # x больше, чем y
x < y # x меньше, чем y
x >= y # x больше или равно y
x <= y # x меньше или равно y

Хотя это и просто для понимания, операторы в python не эквивалентны математическим операторам. Наиболее распространенной ошибкой является использование оператора = вместо ==. Помните, что = - это оператор присвоения, а == - оператор сравнения. И еще, нет таких операторов как =< или =>.

4.3 Логические операторы

Есть три логических оператора: and, or, not. Значение этих операторов в python совпадает с их значением в английском языке. Например, x > 0 and x < 10 - истинно, только когда x больше нуля И меньше десяти.

n % 2 == 0 or n % 3 == 0 - истинно, когда хотябы одно из выражений истинно, т.е. когда n делиться без остатка на 2 ИЛИ на 3.

И, наконец, оператор not возвращает обратное логическое значение, так not(x > y) истинно, если (x > y) ложно, когда x меньше или равно y.

4.4 Условные вычисления

Для того, что бы написать полезную программу, нам практически всегда нужно проверить условие и соответствующе изменить исходные данные. Условные операции помогут нам в это. Самая простая из них, это операция if.

if x > 0:
    print "x - положительное число"

Булево выражение, которое стоит после оператора if, называется условием. Если условие истинно, включенное выражение выполнится. Если ложно - ничего не произойдет.

Синтаксис операции if следующий:

if БУЛЕВО ВЫРАЖЕНИЕ:
    ОПЕРАЦИИ

Все выглядит так же, как и в объявлении функции, которое мы рассмотрели в прошлой главе, - выглядит так же, как и в остальных составных выражениях: заголовок и тело. Заголовок начинается с ключевого слова if, за ним следует булево выражение и после - двоеточие.

Операции, расположенные ниже с отступом относительно заголовка, являются блоком. Этото блок в составных выражениях называется телом.

Каждое выражение в теле выполняется по порядку, если условное выражение в заголовке возвращает истину - True. Выражение в теле пропускаются, если логическое выражение в заголовне возвращает ложь - False.

Не существует ограничений на количество выражений, которое можно разместить в теле, но там должно находиться хотя бы одно. Иногда необходимо, чтобы в теле ничего не происходило (например, если код в теле вы планируется написать позже). В этом случае, можно воспользоваться операцией pass, которая ничего не делает.

if True: # Это выражение всегда вернет истину,
    pass

4.5 Операции ветвления

Второй формой операции if является выполнение ветвления, когда есть два возможных варианта выполнения вычислений. Синтаксис выглядит следующим образом:

if x % 2 == 0:
    print x, "is even" # четное
else:
    print x, "is odd" # нечетное

Если остаток от деления на два равен нулю, значит число x четное и мы видим на экране соответствующий результат. Если условие не верно, выполняется второе выражение. Условие должно возвращаться истину или ложь, в соответствии с этим будет выполняться первое или второе выражение.

Как вариант, для проверки четности числа, вы можете поместить этот код в функцию:

def print_parity(x):
    if x % 2 == 0:
        print x, "is even"
    else:
        print x, "is odd"

Для любых значений x, функция print_parity показывает соответствующее сообщение. Когда вы вызываете ее, можете передавать любое целочисленное выражение в качестве аргумента.

>>> print_parity(17)
17 is odd.
>>> y = 41
>>> print_parity(y+1)
42 is even.

4.6 Сложное условие

Иногда требуется более двух исходов выражения и требуется больше веток решений. Одним из способов является использование сложных составных условных выражений:

if x < y:
    print x, "is less than", y
elif x > y:
    print x, "is greater than", y
else:
    print x, "and", y, "are equal"

elif - это аббривиатура else if. Опять таки, выполнится только одна ветвь вычислений. Нет ограничений на количество выражений elif, но выражение else может быть только одно, и оно должно быть последним.

if choice == 'a':
    function_a()
elif choice == 'b':
    function_b()
elif choice == 'c':
    function_c()
else:
    print "Invalid choice."

В каждой ветви проверяется условие. Если первое возвращает ложь, проверяется следующие, и так далее. Если любое из условий возвращает истину, соответствующая ветвь запускается на исполнение и сложное услоное выражение заканчивается. Если более одного выражения возвращают истину, выполняется только первое.

4.7 Вложенные условия

Одно условное выражение может быть вложено в другое. Мы можем переписать наш код следующим образом:

if x == y:
    print x, "and", y, "are equal"
else:
    if x < y:
        print x, "is less than", y
    else:
        print x, "is greater than", y

Внешнее выражение имеет две ветви. Первая ветвь содержит простую операцию. Вторая ветвь содержит вложенное условное выражение, тоже состоящее из двух ветвей, которые могли бы также содержать вложенные условия.

Хотя отступы и деляют структуру выражения четче, вложенность усложняет быстрое чтение кода. Вложенность, это хорошая идея, но старайтесь ей сильно не увлекаться.

Логические операторы часто используются для упрощения вложенных выражений. Например, мы можем переписать следующий код используя одно условное выражение:

if 0 < x:
    if x < 10:
        print "x is a positive single digit." # х - положительное число меньше 10

Операция print выполнится только тогда, когда выполнятся оба условия, так что мы можем воспользоваться оператором and:

if 0 < x and x < 10:
    print "x is a positive single digit."

Этот тип условных выражений является общим, в python возможна другая нотация, похожая на математическую:

if 0 < x < 10:
    print "x is a positive single digit."

Это выражение семантически равносильно булевым и вложенным выражениям.

4.8 Операция return

Операция return позволяет прервать вычисления внутри функции. Одной из причин использования этой операции является отслеживание ошибок:

def print_square_root(x):
    if x <= 0:
        print "Positive numbers only, please." # введите положительное число
        return

    result = x**0.5
    print "The square root of", x, "is", result

Функция print_square_root имеет параметр x. Первым делом проверяется знак переданного числа. В случае, если передано отрицательное число, выводится сообщение об ошибке и работа функции завершается. Поток вычисления возвращается к точке вызова и оставшаяся часть функции не выполняется.

4.9 Ввод с клавиатуры

Для ввода данных с клавиатуры в python используются две встроенные функции: raw_input и input. Давайте рассмотрим их поближе.

Когда вызывается одна из этих функций, программа приостанавливается и ожидает, когда пользователь введет данные с клавиатуры. Когда пользователь нажимает на клавишу Enter, программа возобновлется, а функция raw_input возвращает введенные данные в виде строки:

>>> my_input = raw_input()
What are you waiting for?
>>> print my_input
What are you waiting for?

Прежде чем вызывать функцию raw_input, было бы неплохо сообщить пользователю, какого типа инфорацию ему нужно ввести. Эта информация называется приглашением. Мы можем передать приглашение в качестве аргумента функции raw_input:

>>> name = raw_input("What...is your name? ")
What...is your name?
Arthur, King of the Britons!
>>> print name
Arthur, King of the Britons!

Обратите внимание, что приглашение - это строка, поэтому аргумент нужно заключать в кавычки.

Если вы ожидаете ввода целого числа, можете воспользоваться функцией input:

prompt = "С какой скоростью летает ласточка?\n"
speed = input(prompt)

Если пользователь вводит строку из чисел, интерпретатор конвертирует ее в целое число и привязывает к переменной speed. К сожалению, если пользователь введет хотя бы одну букву, программа завершиться по ошибке:

>>> speed = input(prompt)
С какой скоростью летает ласточка?
Про какую ласточку вы говорите, африканскую или европескую?
... SyntaxError: invalid syntax

В этом примере, если заключить ответ в кавычки, сообщения об ошибке не последует:

>>> speed = input(prompt)
С какой скоростью летает ласточка?
"Про какую ласточку вы говорите, африканскую или европескую?"
>>> speed
'Про какую ласточку вы говорите, африканскую или европескую?'
>>>

Для того, чтобы обойти такого рода ошибки, можно работать с функцией raw_input с дальнейшим преобразованием ответа в нужный тип данных.

4.10 Преобразование типов

Каждый тип в python сопровождается соответствующей встроенной функцией преобразования в указанный тип. Команда int(АРГУМЕНТ), например, преобразует любое значение в целое число, если это возможно, или выдает предупреждение о невозможности преобразования:

>>> int("32")
32
>>> int("Hello")
ValueError: invalid literal for int() with base 10: 'Hello'

Функция int так же может преобразовать дробное число в целое, отбросив дробную часть:

>>> int(-2.3)
-2
>>> int(3.99999)
3
>>> int("42")
42
>>> int(1.0)
1

Функция float(АРГУМЕНТ) преобразует строку или целое число в дробное:

>>> float(32)
32.0
>>> float("3.14159")
3.14159
>>> float(1)
1.0

Python различает целое число 1 и дробное - 1.0. По идее, это одно и тоже число, но представленное разными типами данных. Для компьютера 1 и 1.0 - не одно и тоже.

Команда str(АРГУМЕНТ) преобразует любой аргумент в строку:

>>> str(32)
'32'
>>> str(3.14149)
'3.14149'
>>> str(True)
'True'
>>> str(true)
Traceback (most recent call last): File "<stdin>", line 1, in <module>
NameError: переменная 'true' не определена

Функция str(АРГУМЕНТ) работает с любыми значениями, преобразовывая их в строки. Как говорилось ранее, True - это булево значение, а true - нет.

Для булевых значений, ситуация более интересна:

>>> bool(1)
True
>>> bool(0)
False
>>> bool("Ni!")
True
>>> bool("")
False
>>> bool(3.14159)
True
>>> bool(0.0)
False

Python может преобразовать любое значение в булево. Для целых и дробных чисел ноль - это False (Ложь), а любое другое число - True (Истина). Для строк, пустая строка - ложь, не пустая - истина.

4.11 GASP

GASP (Graphics API for Students of Python) - Графический API для изучающих python - позволяет писать программы с использованием графики. Прежде чем использовать GASP, его нужно установить на ваш компьюетр. Если вы используете Ubuntu GNU/Linux, посмотрите GASP в Приложении А. Конкретные инструкции по установке GASP для других платформ можно найти на http://dev.laptop.org/pub/gasp/downloads.

После установки gasp, попробуйте следующий скрипт:

from gasp import *

begin_graphics()

Circle((200, 200), 60)
Line((100, 400), (580, 200))
Box((400, 350), 120, 100)

update_when('key_pressed')
end_graphics()

Предпоследняя команда в скрипте приостанавливает выполнение программы до нажатия пользователем любой клавиши на клавиатуре. Без этой команды, окно появится и тут же закроется.

Запустите скрипт. Должно появиться окно с нарисованными фигурами.

Мы воспользовались gasp, чтобы показать некоторые возможности подходов программирования и немного разбавить скучное повествование. Вы можете почитать про GASP поподробнее в приложении Б.

4.12 Словарь

Преобразование типов данных - принудительная операция, которая беред значение одного типа и вычисляет связанное значение другого типа.
Упаковка кода в функцию - процесс добавление заголовка и параметров к последовательности кода программы. Это очень полезный подход, особенное если этот участок кода будет использоваться несколько раз.

4.13 Упражнения

Попробуйте вычислить следующие выражение у себя в голове, затем воспользуйтесь интерпретатором python для проверки:

>>> 5 % 2
>>> 9 % 5
>>> 15 % 12
>>> 12 % 15
>>> 6 % 6
>>> 0 % 7
>>> 7 % 0

Что произойдет в последней строке? Почему? Если вы предвидели все ответы, которые выдаст python, кроме последнего, значит можно двигаться дальше. Если нет, потренируйтесь еще. Постарайтесь понять механизм работы оператора взятия остатка от деления.

if x < y:
    print x, "is less than", y
elif x > y:
    print x, "is greater than", y
else:
    print x, "and", y, "are equal"

Оберните этот код в функцию compare(x,y). Вызовите ее три раза так, чтобы превый аргумент был меньше, потом больше, затем равен второму.

Для большего понимание булевых операций, полезно позаниматься построением таблиц истинности. Два булевых выражения логически эквивалентны только в том случае, если одинаковы их таблицы истинности.

Следующий скрипт python выводит на экран таблицу истинности для любых булевых выражений, состоящих из двух значений: p и q.

expression = raw_input("Enter a boolean expression in two variables, p and q: ")

print " p q %s" % expression
length = len( " p q %s" % expression)
print length*"="

for p in True, False:
    for q in True, False:
        print "%-7s %-7s %-7s" % (p, q, eval(expression))

Как работает этот скрипт, мы разберем в следующих главах. Сейчас нам просто нужно разобраться, как работают булевы выражения. Скопируйте эту программу в файл p_and_q.py, запустите его из командной строки и введите p or q после строки приглашения. Должны получить следующий вывод:

p q p or q
======
True True True
True False True
False True True
False False False

Мы увидели, как ведет себя скрипт. Теперь можно обернуть его в функцию:

def truth_table(expression):
    print " p q %s" % expression
    length = len( " p q %s" % expression)
    print length*"="

    for p in True, False:
        for q in True, False:
            print "%-7s %-7s %-7s" % (p, q, eval(expression))

Мы можем импортировать ее в оболочку python и вызвать ее, передав булево выражение в качастве аргумента:

>>> from p_and_q import *
>>> truth_table("p or q")
p q p or q
=====================
True True True
True False True
False True True
False False False
>>>

Попробуйте следующие буллевы выражения с нашей функцией, посмотрите, какие таблицы истинности получаться:

not(p or q)
p and q
not(p and q)
not(p) or not(q)
not(p) and not(q)

Какие из них являются логически эквивалентными?

Введите следующие выражения в оболочке python:

True or False
True and False
not(False) and True
True or 7
False or 7
True and 0
False or 8
"happy" and "sad"
"happy" or "sad"
"" and "sad"
"happy" and ""

Проанализируйте результаты. Что происходит, когда в логической операции участвуют значение различных типов? Сможете ли вы составить правила для выражений с операторами and и or?

if choice == 'a':
    function_a()
elif choice == 'b':
    function_b()
elif choice == 'c':
    function_c()
else:
    print "Invalid choice."

Оберните этот код в функцию dispatch(choice). Затем определите функции function_a, function_b и function_c, которые выводили бы сообщение, какую функцию мы вызвали. Например:

def function_a():
    print "function_a was called..."

Поместите эти функции (dispatch, function_a, function_b и function_c) в скрипт ch04e05.py. Последней строчкой добавте вызов dispatch('b'). Вывод должен быть примерно следующим:

function_b was called...

Наконец, измените свой скрипт таким образом, чтобы пользователь сам мог ввести данные, например, ‘a’, ‘b’ или ‘c’. Протестируйте работу программы, импортировав функции в оболочку python.

Напишите функцию is_divisible_by_3, которая будет принимать одно целое число и выводить сообщение "Это число делится на три", если число делится на три без остатка, или "Это число не делится на три", в обратном случае.

Теперь напишите подобную функцию с именем is_divisible_by_5.

Обобщите написанные вами функции в функцию is_divisible_by_n(x, n), принимающую два целых числа и сообщающую, делится ли первое число на второе. Сохраните ее в файле ch04e07.py. Импортируйте ее в оболочку и проверте ее работу. Это может выглядеть примерно так:

>>> from ch04e07 import *
>>> is_divisible_by_n(20, 4)
Yes, 20 is divisible by 4
>>> is_divisible_by_n(21, 8)
No, 21 is not divisible by 8

Что появится на экране в итоге выполнения следующего кода?

if "Ni!":
    print 'We are the Knights who say, "Ni!"'
else:
    print "Stop it! No more of this!"

if 0:
    print "And now for something completely different..."
else:
    print "What's all this, then?"

Объясните, как работают эти скрипты.

Следующие gasp-скрипт house.py рисует домик в окружении gasp:

from gasp import * # импорт всех функций из библиотеки GASP

begin_graphics() # открываем полотно

Box((20, 20), 100, 100) # это дом
Box((55, 20), 30, 50) # это дверь
Box((40, 80), 20, 20) # это левое окно
Box((80, 80), 20, 20) # это правое окно
Line((20, 120), (70, 160)) # это левый скат крыши
Line((70, 160), (120, 120)) # это правый скат крыши

update_when('key_pressed') # полотно закроется по нажатию любой кнопки
end_graphics() # закрываем полотно, оно в любом случае закроется, потому что это конец скрипта

Запустите этот скрипт и посмотрите, что получилось.

Оберните получившийся код в функцию draw_house(). Запустите скрипт. Вы видите дом? Почему нет? Добавте вызов функции draw_house() в конце скрипта, дом должен появиться на экране. Добавте в функцию параметры x и у (def draw_house(x, y):), чтобы определять местоположение дома на полотне. Воспользуйтесь функцией draw_house, чтобы разместить на полотне пять домов в разных местах.

Изучите Приложение Б для большего понимания работы GASP.

Для того, чтобы закрасить крышу дома, можно вместо рисования двух линий воспользоваться инструментом Polygon с параметром filled=True.

Внимание! Этот перевод, возможно, ещё не готов.
Его статус: идёт перевод

Переведено на Нотабеноиде
http://notabenoid.org/book/9398/29187

Переводчики: czech

Настройки

Готово:

100.00% КП = 1.0