Содержание
Несколько мелочей
Сегодняшний рассказ очень короткий – чтобы у вас было побольше времени на решение задач. И очень отрывочный: это маленькая свалка разной степени полезности сведений и внушений.
1. abs
Первым делом ссылка на документацию. Для решения задачи номер 6 (тем, кто до неё дойдёт), может пригодиться функция abs. (Это же заодно и намёк на подсказку к решению).
2. None, True, False
В предыдущем задании функция min должна в некоторых случаях возвращать None. Эта постановка задачи многих из вас смутила.
Поясняю.
В питоне есть три константы, которые как слышатся, так и пишутся – без кавычек и с большой буквы. Имя им: True, False, None.
Важно понимать ещё и то, что это просто такие константы. Питон не воспринимает, например, None, как указание, что где-то ничего нету. Это всего лишь способ для программиста сказать себе самому, что где-то что-то могло быть, а есть ничто.
С другой стороны, питон иногда сам говорит этими словами: если вы не указали, что возвращает функция, то её значение будет None; если вы написали верное логическое выражение (например 1 == 1), то его значением будет True, а если ложное, то False.
3. Операции сравнения: is, in
Повторю снова про операции сравнения.
Для начала, напомню то, на чём я не акцентировал ваше внимание: в питоне строго различается сравнение и присваивание. Некоторых это путает. Сравние пишется так: x == y или 1 == 2. Это выражение, значением которого является True или False. Присваивание пишется так: x = y. Это действие: записать в x то, что лежало в y.
Я уже упоминал о таких операциях сравнения: ==, != (не равно), >, <, >=, <=.
Новая операция сравнения: is. Оно похоже на ==, только == проверяет на равенство (например, для двух списков эта операция будет по очереди брать элемент из одного и из другого списка и сравнивать их), а операция is проверяет на совпадение. Если вспомнить рисунки про червяков и стрелочек, то x is y отвечает на вопрос: ведут ли стрелочки от x и y к одному и тому же объекту.
Все эти умные слова понимать особо не нужно. Основное и почти единственное практическое применение для is состоит в том, чтобы сравнивать значение с None.
Если где-то нужно проверить значение на None, то делать это нужно так и только так (это вопрос совместимости между разными версиями питона):
Двойственное к is сравнение: is not. Оставляю вам в качестве упражнения на английский язык догадаться, что оно означает.
Ещё одна полезная операция сравнения: in – проверяет принадлежность элемента списку. Например:
(Для зануд: как правило, in сравнивает значения при помощи ==)
Наконец, последняя операция сравнения: not in. Снова оставляю вам на самостоятельное догадывание.
4. print vs. return
Так как мы начинали курс с диалогов с питоном, (суть которых состоит в том, что вы вводите выражение, а питон печатает его значение), то у некоторых из вас перепутались в голове ключевые слова print и return.
Посмотрим на два примера:
Разницу между ними можно увидеть даже в диалоге с питоном, хотя она и не будет очень уж понятной:
Существенным и понятным различие между ними станет, когда мы окончательно отклеимся от диалогов с командной строкой питона и будем писать полноценные программы.
Пока что же я буду просто занудствовать и требовать, чтобы там где в условии написано "...печатает...", вы использовали print, а там, где написано "...возвращает..." – соответственно return.
5. О побочных эффектах
В некоторых языках программирования (в голову приходит только паскаль, с некоторой натяжкой – хаскель) есть два различных понятия: процедура и функция. Процедурой называется последовательность команд (ну, приблизительно), а функцией называется примерно то же, только оно ещё и возвращает результат.
В питоне на всё про всё используется одна и та же конструкция, но зато есть оговоренные традиции, что эти два понятия нужно различать. Традиции такие:
Если функция возвращает какое-то значение, то единственное, что можно делать в этой функции – это вычислять это значение. Такая функция не должна ничего печатать, не должна никак менять глобальные переменные (хорошо, что я вам не рассказал, что это такое и вы этого всё равно не умеете) и т.п. Тело такой функции всегда завершается конструкцией return значение.
Если в функции, которая возвращает значение, в начале есть проверки, и нам хочется как-то обозначить, что ей не годятся аргументы, то мы напишем в этих проверках return None. (Пока что, покуда мы не знаем более хитрого подхода на этот случай).
Если же функция призвана делать какое-то действие – печатать на экран, писать в файл – то такая функция не будет ничего возвращать. Тело такой функции не завершается return, а если в начале у неё и приходится делать какие-то проверки, то соответствующие их ветки будут завершаться конструкцией return без аргументов – дабы символизировать, что в этом месте выполнение функции прекращается.
Из этого правила есть много исключений, но все они всегда обязательно должны быть описаны в документации к функции. (Пока что у нас нету документации в функциях, и в роли такой документации мы используем текст задачи).
6. Ещё о побочных эффектах
Вспомним описание функции min из прошлого задания.
Из этого описания нам казался бы логичным такой диалог с питоном:
А теперь предположим, что функция min у нас определена так:
Такая функция будет укладываться в те условия, которые для неё указаны в задаче (ибо я не старался сильно занудствовать в описании условий, даже наоборот), но вот такого диалога, который мы предположили логичным, для неё не получится. Человек, не знающий о том, как она устроена, будет неприятно удивлён, обнаружив, что она коцает список, который ей дают просто посмотреть.
К счастью, даже сама возможность попортить аргументы у нас есть только в случае со списками (из тех типов, которые мы уже знаем).
Отсюда правило: когда у нас аргументом идёт список (или какая-нибудь ещё мутируемая – так это приято называть – структура), мы действуем осторожно и стараемя его не попортить.
7. +=, ...
Наконец, пара просто полезных мелочей, которые можно использовать, а можно и не использовать – кому как нравится.
Мелочь первая.
Довольно часто у вас будет возникать конструкция вида x = x + 1. Для этой конструкции есть сокращённая запись: x += 1. Людям, знакомым с Си или Си-образными языками (в их числе перл и ява) эта конструкция уже знакома. Тем, кто видит такое в первый раз, выбор: или привыкать, или избегать.
Такие же сокращения есть и для кучи других операций: *=, /=, %= и так далее.
8. Tuple unpacking
Мелочь вторая.
Предположим, у вас есть список, про который вы абсолютно точно заранее знаете, что в нём ровно два элемента. Тогда можно одной строкой присвоить этим элементам имена:
Аналогично для трёх и более элементов.
Есть такая же конструкция и для одного элемента, но она выглядит несколько неказисто:
Если число элементов списка не равно числу переменных, в которые мы пытаемся список разобрать, питон будет ругаться. (Словами вроде too few или too many values to unpack).
9. Длинные записи в darcs
Как все, надеюсь, помнят, ваши решения задач я принимаю только через darcs. И более того, придираюсь к тому, как вы подписываете ваши изменения.
Некоторые из вас уже столкнулись с вопросом: а как подписывать изменения, если их много и сразу и разных.
Хороший ответ такой: их нужно записывать по чуть-чуть, так чтобы по истории изменений можно было всё понять. Ровно для этого darcs про каждый чих спрашивает: "а это записать? А это записать?"
Но есть и плохой, негодный, но всё же ответ на случай, если всё-таки хочется записать всё скопом, а я не очень придирался бы к описанию: когда darcs спросит "do you want to add a long comment?", отвечаете ему "y". darcs вас выбросит в текстовый редактор, где до строки со звёздочками вам предлагается описать изменения, а после неё идёт несколько подсказок со стороны darcs. Примерно неделю назад я перенастроил kodomo и kodomo-count таким образом, чтобы после этого darcs вас выбрасывал не в vi (который на вас всех навёл, надеюсь, ужас, тем, что даже выйти из него непонятно, как), а в nano, который суть очень простой и примитивнейший редактор, но в нём всё работает, как ожидается и внизу экрана всегда есть подсказка.
Если вы всё-таки стали писать многострочный комментарий к изменению в репозитории, придерживайтесь следующей традиции:
Первая строка с коротким описанием сути всего * вторая строка пустая * третья и далее строки начинаются со звёздочек * в них пишется про каждое отдельное изменение
10. Задачка
Не корысти и злого умысла ради, а исключительно дабы определить тему следующего занятия, завершал я лекцию такой задачкой:
Опишите функцию diff, которая на вход она получает список чисел, для каждой пары соседних элементов считает их разность, и возвращает список получившихся разностей.
Например: