Северенс Ч. - Введение в программирование на Python - 2016. Введение в программирование на Python Ч. Северенс М. Национальный Открытый Университет "интуит", 2016
Скачать 0.65 Mb.
|
Добавление новых функцийРанее мы использовали встроенные в Python функции . Теперь мы рассмотрим, как добавлять новые функции. Определение функции (fuпction defiпitioп) задает имя новой функции и последовательность инструкций , которые выполняются, когда функция вызывается. Как только мы определили функцию, мы можем многократно ее использовать. Например, def priпt_lyrics(): priпt '1'm а lшnberjack, and I'm okay." priпt '1 sleep all night and I work all day.' de f - это ключевое слово, которое показыва ет, что далее следует определение функции. Имя функции - pr i nt l yr i c s . Правила наименования функций таки же, как для переменных: возможны буквы, числа и некоторые знаки пунктуации, но первая буква не может быть числом. Вы не можете использовать ключевые (зарезервированные) слова в качестве имен функций. Имена функций и переменных не должны совпадать. Пустые скобки после имени указывают на то, что функция не принимает аргументов . Позже мы рассмотрим функции, которые принимают входные аргументы. Первая строка определения функции называется заголовком (header), оставшаяся часть - телом (body) функции . Заголовок заканчивается двоеточием, тело функции имеет отступ. По договоренности, отступ всегда является четырьмя пробелами. Тело функции может содержать любое количество инструкций . Строки, которые мы выводим на экран, заключены в двойные кавычки. Одиночные и двойные кавычки взаимозаменяемы, большинство людей используют одиночные кавычки, за исключением тех случаев, когда одиночные кавычки встречаются внугри строки. Если вы будете набирать функцию в интерактивном режиме, то Pythoп для тела функции сделает отступы, а в конце необходимо будет ввести пустую строку. Определение функции создает переменную с таким же именем . >>> prh1t prmt_lyrics >>> prh1t type(prmt_lyrics) Значением prmt_lyrics является функциональный объект (fuпctioп object), кото рый имеет тип 'fiшction'. Синтаксис вызова новой функции похож на вызов встроенной функции: >>> prh1_t lyrics() I'm а lшnЬerjack, and I'm okay. 1 sleep all night апd I work all day. Однажды определив функцию, вы можете использовать ее внугри других функций. Для примера повторим строку-п рипев, воспользовавшись новой функцией: def repeat_lyrics(): prшt_lyrics() prшt_lyrics() Затем вызовем repeat_lyrics: >>> repeat_lyrics() I'm а lшnberjack, and I'm okay. 1 sleep all night апd I work all day. I'm а lшnЬerjack, and I'm okay. 1 sleep all night апd I work all day. Определение и использование Если собрать вместе весь код из предыдущего параграфа, то получим следующее: def print_lyrics(): print "I'm а lшnberjack, апd I'ш okay." print '1 sleep all пight апd I work all day.' def repeat_lyrics(): print_lyrics() print_lyrics() repeat_lyrics() Эта программа содержит два определения функций: р r i n t 1 уr i с s и repeat lyr i cs. Определения функций получают управление подобно другим инструкциям, результатом является создание функционального объект. Инструкции внутри функции не получат управления, пока функция не будет вызвана. Как и следовало ожидать, вы должны предварительно создать функцию, прежде чем сможете ее выполнить. Иными словами, определение функции должен быть выполнено перед ее первым запуском. Поток исполнения Для того чтобы убедиться, что функция определяется до ее первого использования, вы должны знать порядок, в котором выполняются инструкции , он называется потоком исполнения (tlow of executioп). Исполнение обычно начинается с первой инструкции программы . Инструкции выполняются по одной сверху вни з. Определение функций не изменяют порядок исполнения программы, но запомните, что инструкции внутри функции не испо лн яются до вызова функции. Вызов функции подобен обходному пуги в потоке исполнения. Вместо того чтобы перейти к следующей инструкции, поток переходит в тело функции, выполняет все инструкции внугри тела, и затем возвращается обратно в то место, которое он покинул в момент вызова функции . Это звучит достаточно просто, пока вы не вспомните, что одна функция может вызывать другую. В то время как в середине одной функции, программа может выполнять инструкции из другой функции. Но во время выполнения этой новой функции, программа может выполнять еще одну функцию! К счастью, Руt]юп следит, где находится, так что всякий раз, когда функция завершается, программа переходит обратно , в место вызова функции. Программа завершится, когда дойдет до конца программы. В чем мораль этой неприглядной истории? Когда вы читаете программу, вам не всегда хочется читать сверху вниз. Иногда это имеет смысл, если вы следуете за потоком исполнения. 8.8. Параметры и аргументыНекоторые из встроенных функций требуют пер едачи входных аргументов. Например, когда вы вызываете ma t h . s i n, вы передаете число в качестве входного аргумента. Некоторые функции принимают больше одного аргумента, наприме р, в mat h . pow передается два аргумента: основание и степень. Внугри функции, аргументы , присвоенные переменным, называются парамет рами (parameters). Пример определения функции, которой передается аргумент: def print_twice(Ьruce): print bruce print bruce Эта функция присваивает аргумент параметру с именем br uc e . Когда вызыва ется функция, она дважды выводит на экран значение параметр а (что бы это ни было). Эта функция работает с любыми значениями, которые могуг быть выведены на экран. >>> priпt_twice('Spam') Spam Spam >>> priпt_twice(l 7) 17 17 >>> priпt_twice(matЬ.pi) 3.14159265359 3.14159265359 Для построения функций, определяемых пользователем, используются те же правила , что и для встроенных функций, поэтому мы можем использовать любое выражение в качестве аргумента для pr i n t t w i c e : >>> priпt_twice('Spam '*4) Spam Spam Sраш Spam Spam Spam Sраш Spam >>> priпt_twice(matl1.eos(matl1.pi)) -1 .0 -1.0 Аргумент вычи сляется перед вызовом функции, поэтому в примере выражения 'Sраш'*4 и math.cos(math.pi) вычисляются только один раз. Вы можете использовать переменные в качестве аргументов: >>> micl1ael = 'Eric, fue l1alf a Ьее.' >>> priпt_twice(michael) Eric, tl1e l1alf а Ьее. Eric, tl1e l1alf а Ьее. Имя переменной, которое мы передаем в качестве аргумента (michael), не имеет ничего общего с параметром (bruce). Не важно, какое значение было передано в вызывающую функцию; здесь, в priпt_ twice, мы называем все bruce. Плодотворные (fruitful) функции и vо id-функции Некоторые из функций, которые мы используем, такие, как математические функции, возвращают результаты (приносят плоды); за неимени ем лучшего названи я, я назы ваю их плодотворными функциями (fruitful fimctions) . Другие функции, подобные pr i n t _ t wi c e , в ыполняют некоторые действия, но не возвращают значение. Они называются vоid-функциями. Когда вы вызываете плодотво рную функцию, вы почти всегда хотите сделать что-то с результатом, например, вы можете присвоить его переменной или использовать его как часть выражения: х = math.cos(radians) golden = (math.sqrt(S) + 1) / 2 Когда вы вызываете функцию в интерактивном режиме, Pythoп отображает результат: >>> math.sqrt(S) 2.2360679774997898 Но если вы вызываете плодотворную функцию в скрипте и не сохраняете результат выполнения функции в переменной, то возвращаемое значение растворится в тумане! matl1.sqrt(S) Этот скрипт вычисляет квадратный корень из 5, но так как он не сохраняет результат в перем енной и не отображает результат, то это не очень полезно. Vоid-функции могут отображать что-то на экране или производить другие действия, но они не возвращают значение. Если вы попытаетесь присвоить результат выполнения такой функции переменной , то получите специальное значение, называемое None. >>> resuh = print_twice('Bing') B.iпg Bing >>> priпt result Nопе Значение Nопе - это не тоже самое, что строка 'N опе'. Это специальное значение, которое имеет собственный тип: >>> priпt type(Noпe) Для возврата результата из функции, мы используем инструкцию returп в функции. Для примера, мы можем создать простую функцию с именем addtwo, которая складывает два числа и возвращает результат. def addtwo(a, Ь): added = а + Ь returп added х = addtwo(З, 5) priпt х Когда скрипт выполнится, инструкция priпt напечатает "8". Внутри функции параметр ы а и Ь, в момент выполнения, будут содержать значения 3 и 5 соответственно . Функция подсчитывает сумму двух чисел и помещает ее в локальную переменную ad de d. Затем с помощью инструкции rеtшп результат вычисления возвращается в вызываемый код, как результат выполнения функции. Далее результат присваивается переменной х и выводится на экран. Зачем нужны функции?Есть несколько причин, на основании которых программу стоит разбивать на функции. Создание новой функции предоставляет вам возможность присвоить имя группе инструкций. Это позволит упростить чтение, понимание и отладку программы. Функции позволяют сократить код про граммы, благодаря ликвидации повторяющихся участков кода. Позже, вы сможете вносить коррективы только в одном месте. Разбиение длинной программы на фующии позволяет одновременной отлаживать отдельные части, а затем собрать их в единое целое. Хорошо спроектированная фующия может использоваться во множестве программ. Однажды написав и отладив функцию, вы можете использовать ее множество раз. 8.13. Словарь Алгоритм (algorithm): обобщенный подход к решению категории проблем. Аргумент (argшnent): значение, передаваемое функции , в момент ее вызова. Это значение присваивается соответствующему параметру в функции. Тело функции (body): последовательность инструкций внутри определения функции. Детерминистический (deterrnirustic): относится к программе, которая выполняет одинаковые действия при одинаковых входных значени ях. Точечная нотация (dot notation): синтаксис для вызова функции из другого модуля. Поток исполнения (flow of execнtion): порядок, в котором выполняются инструкции во время работы программы. Плодотворная функция (fruitful function): функция, которая возвращает значение. Функция (fuпctioп): это именованная последовательность инструкций, которая выполняет некоторые полезные действия. Функции могут иметь или не иметь аргументы, могут возвращать или не возвращать результат. Вызов функции (functioп call): инструкция, которая выполн яет функцию. Она содержит имя функции и список аргументов. Оп ределение фующии (function definition): инстру щия, которая создает новую функцию; задает имя функции, параметры и инстру щии для выполнения. Функциональный объект (functioп object): значение, созданное определением функции. Имя функции является переменной, которая ссылается на функциональный объект. Заголовок функции (header): первая строка в определении функции. Инстру щия импорта (import statemeпt): инстру щия, которая читает файл модуля и создает модульный объект. Модульный объект (module object): значение, которое создает инстру щия импорта, для предоставления доступа к данным и коду, определенном в модуле. Параметр (parameter): имя, используемое внутри функции, которое ссылается на передающееся в качестве аргумента значение. Псевдослучайн ый (pseudorandom): относится к последовательности чисел, которые похожи на случайные, но генери руются детермини рованной программой. Возвращаемое значение (rеtшп value): результат выполнения функции. Vоid-функция (void functioп): функция, которая не возвращает результирующего значения. Создаем первую функцию Видео Итерации Видео Обновление переменной Общим шаблоном в инструкциях присваивания является инструкция присваивания, которая обновляет переменную, где новое значение переменной зависит от старого: х= x+l Это означает "получить текущее значение х, прибавить к нему 1 и затем обновить х, присвоив ему новое значение". Если вы попытаетесь обновить переменную, которая не существует, то получите ошибку, т.к. Python вычисляет правую сторону раньше ее присваивания переменной х: >>> х = x+l NameEп or: name 'х' is not defined Перед тем как обновить переменную, инициализировать (irutialize), обычно с присваивания: >>> х = о >>> х = x+l вам необходимо ее помощью простого Обновление переменной, инкрементом (iпcrement), (decremeпt). путем прибавления к ней 1, называется вычитание 1, называется декрементом Инструкция while Компьютеры часто используются для автоматизации повторяющихся задач. Повторение сходных или простых задач без ошибок - это то, что компьютер делает лучше, чем человек. Поскольку итерации распространены, Руtlюп предоставляет несколько языковых особенностей для их создания. Одной из форм итераций в Руtlюп является инструкция wh i 1 е . Далее представлена простая программа, которая производит обратный отсчет от 5 и затем говорит 'Blastoff!". п = S while п > О: priпt п п = п-1 print 'Blastoff!' Вы таюке можете читать инструкцию wh i 1 е , как если бы это был английский язык. Это означает, "до тех пор, пока п больше О, выводить на экран значение п и уменьшать п на 1. Когда достигнем О, покинуть инструкцию while и вывести на экран слово Blastoff!" Более формально, поток выполнения для инструкции whi le имеет следующий вид: Вычисление условия, получаем True или False. Если условие ложно, то выходим из инструкции while и продолжаем выполнение со следующей инструкции. Если условие истинно, то выполняем тело и затем возвращаемся на шаг 1. Этот тип потока называется циклом (loop), т.к. третий шаг цикла возвращается на начало. Выполнение тела цикла называется итерацией (iteratioп). Для приведенного выше цикла, мы бы сказали, что "прошло 5 итераций", т.е. тело цикла было выполнено 5 раз. Тело цикла должно изменять одно или более переменных, что в конечном итоге приведет к ложности условия и завершению цикла. Переменные, которые изменяются каждый раз при выполнении цикла и контролируют завершение цикла, называются итерационными перемен ными (iteration variaЬle). Если итерационная переменная в цикле отсугствует, то такой цикл будет бесконечным (infinite loop). Бесконечные циклы Бесконечным источником развлечения для программистов является высказывание на руководстве по шампуню: 'Н амылить, промыть, повторить". Это бесконечный цикл, поскольку в нем отсугствует итерационная переменная, которая указывает на количество выполнений в цикле. В случае с обратным отсчетом, мы можем удосто ве ри ться , что цикл завершится, т.к. мы знаем, что значение 11 конечно , мы можем увидеть, что значение n каждый раз уменьшается и в конечном итоге станет равным нулю. "Бесконечные циклы" и break Ин огда вы не знаете, когда завершить цикл, пока не достигните некоторого значения в теле. В этом случае, вы можете специально написать бесконечный цикл и затем исполь зовать инструкцию b r e a k, чтобы из него выйти. Это явно бесконечный цикл, т.к. логическое выражение в инструкции wh i l e содержит True: n = 10 wl1ile True: pr:i11tn, n = 11- 1 print 'Done!' Если вы совершите ошибку и запустите этот код, то быстро научитесь, как останавливать процесс Python в вашей системе или найдете кнопку выключения питания на вашем компьютере (что делать не желательно). Эта программа работает постоянно или пока не разрядится батарея, т.к. логическое выражение всегда будет истинным. Мы можем добавить в тело цикла код с b r e a k, который позволит выйти из цикла при наступлении заданного условия. Например, предположим, что мы принимаем входные значения с клавиатуры, пока пользователь не наберет "done". Можем записать это следующим образом: wblle True: line = raw _input('> ') nliпe == 'dопе': break print line print 'Done!' Условие цикла является Тr u e , т.е. всегда истинным. Оно будет выполняться, пока на достигнет инструкции прерывания. 1О.5. Завершение итерации с помощью continueИногда вы находитесь в итерации цикла и хотите завершить текущую итерацию и сразу перейти к следующей итерац ии. В этом случае можно воспользоваться инструкцией c o nt i nue, которая пропускает текущую итерацию и переходит к следующей без завершения тела цикла. Далее представлен пример цикла, который копирует данные, поступающие на его вход до тех пор, пока не будет введено "done". Если строка начинается с символа #, то она не будет вы води ться на печ ат ь (похоже на комментарии в Pythoп). w\1ile True: line = raw_input('> ') nliпe[O] == '#': continue nliпe == 'dопе': break print line priпt 'Do ne!' Все строки, которые вводятся с клавиатуры, будут выведены на экран, кроме тех, которые начинаются с символа #. Определение циклов с помощью for Иногда мы хотим пройти в цикле через множество (set) вещей, таких как список слов, строки в файле или список чисел. Когда у нас есть подобный список, мы можем построить определенный (defi.пite) цикл с использованием инструкции f оr . Мы вызывали инструкцию wh i l е в неоп ределенных (iпdefi.пite) ци клах, т.к. циклы работали до того момента, пока условие не станет F а l s е . Цикл f о r проходит через известное множество элементов, т.е. столько раз, сколько элементов содержится во множестве . Синтаксис цикла f or похож на цикл wh i l e , здесь есть инструкция for и тело цикла: friends = ['Josepl1', 'Glenn', 'Sally'] for friend in friends: print 'Нар ру New Year:', frieпd print 'Done!' Переменная fr i e n d s является списком (в следующих главах вы об этом узнаете подробнее) из трех строк, цикл for проходит через список и выполняет тело цикла для каждой из трех строк: Нарру New Year: Joseph Нарру New Year: Glenn Нарру New Year: Sally Done! Посмотрите на цикл f о r, здесь f оr и i n являются зарезервированными словами, frieпd и friends являются переменными. for friend in friends: print 'Нарру New Year', friend В частности, f r i e nd является итерационной переменной для цикла f or . Переменн ая fr i e nd изменяется для каждой итерации цикла и контролирует, когда цикл for заверuштся. Шаблоны цикла Часто мы используем циклы for и while длятого, чтобы протий в цикле через элементы списка или содержимое файла в поисках наибольшего или наименьшего значения. Эти циклы обычно строятся по следующей схеме: Иници ализация одной или более переменных до начала выполнения цикла. Выполнение некоторых вычислений для каждого элемента в теле цикла, возможно, изменение переменных в теле цикла. Просмотр результирующих переменных , когда цикл заверuшлся. Воспользуемся списком чисел для демонстрации подходов и создания распространенныхшаблонов. Циклы подсчета Например, для подсчета числа элементов в списке, мы можем написать следующий цикл f o r : сош1t = О for itervar iп [З, 41, 12, 9, 74, 15]: СОШ1t = СОШ1t + 1 priпt 'Со Ш1t: ', сош1t Мы установили начальное значение для переменной coun t равным нулю перед тем, как начать выполнение цикла. Наша итерационная переменная называется i t er v ar . В теле цикла мы добавляем 1 к текущему значению с о u n t для каждого значения в списке. К моменту завершения цикла, значение переменной count будет содержать количество элементов. Другой простой цикл подсчитывает сумму набора чисел: total = О for itervar in [З, 41, 12, 9, 74, 15]: total = total + itervar priпt 'Тotal: ', total Переменная t о t а l накапливает сумму всех чисел, иногда ее называют сумматором (accшnu1ator). На практике для подсчета числа элементов используют встроенную функцию l e n (), а для вычисления суммы элеме нтов - sum ( ) . Циклы максимума и минимумаДля нахождения наибольшего значения в списке или последовательности, создадим следующий цикл: largest = None priпt 'Before:', largest for itervar in [З, 41, 12, 9, 74, 15]: if largest is None or itervar > largest : largest = itervar print 'Loop:', itervar, largest priпt 'Largest:', largest Результат работы программы будет иметь вид: Before: Nопе Loop: 3 3 Loop: 4141 Loop: 12 41 Loop: 9 41 Loop: 74 74 Loop: 15 74 Largest: 74 Переменн ая 1 а r ge s t содержит наибольшее значение, которое существует на данный момент. Перед запуском цикла мы устанавливаем largest вNon e . None - это специальная константа, которая может храниться в переменной и маркировать ее как "пустую". Перед началом цикла, наибольшим значением является None . На первой итерации цикла значение 3 больше Non e , мы устанавливаем l a r ge s t равным 3. На последней итерации в l a r ge s t содержится наибольшее значение. Код для вычисления наименьшего значения: smallest = N one priпt 'Before:', smallest for itervar iп [З, 41, 12, 9, 74, 15]: jf smallest is N опе or itervar < smallest: smallest = itervar print 'Loop:', itervar, smallest priпt 'S mallest:', smallest Снова smallest содержит наименьшее значение. Далее следует простая версия встроенной в Python функции min(): def min(values): smallest = None for value in valнes: if smallest is None or value < smallest: smallest = vaJue return smallest В этой функции меньше кода, мы удалили все инструкции print. 10.9. Словарь Сумматор (accumulator): переменная в цикле, которая используется для накоплени я суммарного результата. Счетчик (counter): переменная, используемая в цикле для подсчета количества встречаемости какого-либо события. Мы инициализируем счетчик нулевым значением, затем инкрементируем его при наступлении какого-либо события . Декремент (decrement): уменьшение значения (обычно на единицу). Инициализация (initialize): присваивание начального значения переменной , которая в дальнейшем будет инкрементироваться (увеличиваться, часто на единицу). Бесконечный цикл (infinite loop): цикл, в котором условие завершения никогда не наступят или для которого нет условия завершения. Итерация (iteratioп): повторное выполнение множества инструкций, используемоепри рекурсивном вызове функции или цикла. Вычисляем среднее значение Видео Строки Видео . Строка - это последовательно сть Строка - это последовательность символов. Вы можете получить доступ к одному символу с помощью оператора скобок: >>> fruit = 'Ьапапа' >>> letter = fuut[l] Вторая инструкция извлекает символ из позиции 1, хранящейся в переменной fruit и помещает его в переменную letter. Выражение в скобках называется индексом (mdex). Индекс обозначает, какой символ в последовательности вы хотите получить: >>> priпt letter а Для болышшства людей, первая буква в 'Ьапапа' это Ь, а не а . Но в Pythoп индекс - это смещение от начала строки, смещение для первого символа - нуль: >>> letter = fuut[O] >>> priпt letter |