Шуман Х. - Python для детей - 2019. # Startwerte festlegen Red (255,0,0)
Скачать 5.95 Mb.
|
Глава Азартная игра 4 92 Рис. 4.4.Пример выполнения программы И еще одна особенность в работе с текстами: здесь также можно использовать символ * для умножения (дублирова- ния) слов, и записать это можно было бы так: Text1 = input() Text2 = "" for Nr in range(0,3) : Text2 += Text1 …но ты можешь укоротить все это вот так: Text1 = input() Text2 = 3 * Text1 Подведение итогов Посмотрим, что у нас с тобой получилось после этой главы. Речь шла о другой управляющей конструкции, которую мы использовали в двух небольших игровых программах. Как и в предыдущей главе, мы использовали эффект случайно- сти. Кроме того, нам везло, и иногда мы получали деньги и выигрывали. В целом же вот что мы узнали нового из языка программи- рования Python: ...и задач 93 time Модуль времени sleep() Ожидание некоторого времени (указывается в секундах) for Для определенного количества элементов списка следует выполнить блок инструкций in range() Управление элементом в диапазоне или списке append() Добавление элемента в список True , False Значения логической переменной или условия not Обратное значение Истина/Ложь для логической переменной или условия [] Диапазон списка или номер элемента списка \ Распределение длинного кода на две строки len() Длина строки + , * Складывает строки | Умножает строки Несколько вопросов... 1. Как сделать так, чтобы компьютер приостановил рабо- ту программы? 2. Что происходит в программе для миллионеров, если ты введешь 0 в качестве значения начального капитала или процентной ставки? 3. Пробел, новая строка, пустая строка: в чем разница? ...и задач 1. Напиши математическую программу, в которой два числа генерируются случайным образом. Другая слу- чайность определяет, нужно ли добавлять, вычитать, умножать или делить эти два числа. Компьютер вы- полнит подсчеты, затем ты сможешь ввести результат. В конце компьютер проверяет, правильно ли введено твое число. 2. Измени игру в угадывания числа так, чтобы ты за- думывал число, а компьютер пытался угадывать его. Указывая «меньше» или «больше», ты сможешь вести компью тер к правильному результату. 3. И еще одна вариация игры в «угадайку»: компьютер играет сам с собой, угадывая число и сравнивая его со своим случайным значением. (Он должен играть «с си- стемой», поэтому никаких случайных догадок!) 94 5 Функции Наши предыдущие программы были небольшими, даже достаточно маленькими, чтобы мы могли увидеть весь ис- ходный код целиком. Но с действительно «большим» про- ектом вроде профессионального приложения или, к при- меру, более сложной игры количество исходного кода будет серьезно увеличиваться. Это означает возможность просто упустить смысл в большом количестве строк кода. Однако если мы разделим большую программу на неболь- шие фрагменты, это поможет нам сохранить, так сказать, «здравомыслие». Итак, в этой главе ты узнаешь: как создавать свои собственные функции с помощью ключевого слова def; как применять параметры; о локальных и глобальных переменных; о ключевом слове return; как менять местами и сортировать числа. Python учится У языка програмирования Python есть базовый словарь, называемый «ключевыми словами». К ним относятся такие слова, как if, for, while, но не print(), input() и int(). Они ин- Python учится 95 тегрируются из базовых модулей, которые импортируются отдельно. Хотя это и происходит автоматически, некоторые моду- ли, такие как random и time, должны быть импортированы в программу с помощью инструкции import (кстати, также ключевое слово). Если же импортированных модулей тебе будет недостаточно, ты всегда можешь создать свои соб- ственные функции. Это означает, что ты сможешь научить язык программиро- вания Python новым словам и, таким образом, постоянно расширять его словарный запас. Это также означает, что Python способен запоминать эти новые изученные слова, и ты сможешь, немного позже, использовать слова из свое- го расширенного словаря в будущих программах. Давай проверим это прямо сейчас. Я просто возьму функ- цию, имя которой я сам придумал: tunix() Конечно, Python ничего не сможет с ней в этот момент сде- лать (рис. 5.1). Рис. 5.1.Ошибка: функция не определена Вот почему мы должны определить код tunix() как функцию, которая ничего особенного здесь не делает, например так: def tunix() : nix = 0 tunix() Ниже идет вызов функции, и, как видишь, ничего в реаль- ности не происходит, что нам с тобой было бы видно в ре- зультате. Глава Функции 5 96 Теперь давай я приведу пример, где будет виден результат работы программы: # Определение функции def sayHello() : print("Привет!") # Вызов функции sayHello() Если ты наберешь эту программу и запустишь ее, то полу- чишь короткое приветствие «Привет!». Прежде чем мы продолжим, ты должен решить, как будешь при- думывать имена функциям. Я решил использовать английские слова. С одной стороны, они часто более лаконичны, чем другие, и все уже существующие функции также имеют английские име- на. Многие профессиональные программисты предпочитают их, часто и для переменных. Но ты всегда можешь использовать свои (например, русские (транслитом)) слова для имен функций, если тебе так больше нравится. Теперь вернемся к нашей новой функции. Она состоит из имени и тела. БлокИнструкций ИмяФункции def () : Немного напоминает условные конструкции, которые ты видел до этого. Начало функции состоит из одной строки. Сначала указывается вводное ключевое слово def, затем имя, всегда сопровождаемое круглыми скобками. def sayHello() : Тело же функции состоит из блока инструкций, в данном случае только из одной инструкции: print("Привет!") Разумеется, эта инструкция используется после строки def. Python учится 97 Как видишь, в коде определение новой функции указывается выше ее вызова. Это необходимо, чтобы интерпретатор Python узнал о функции прежде, чем попытался ее вызвать. И теперь мы создадим новый проект, в котором функции будут определены и, конечно же, немедленно использо- ваны. Как насчет проекта-загадки? Давай посмотрим, что происходит со встроенными функциями. Начнем же мы с функции для начальных значений: def initGame() : Secret = "Я задумал число от 1 до 1000" print(Secret) Attempt = 0 Input = 0 В следующей функции дело касается игры: def playGame() : Case = random.randint(1,1000) while Input != Case : print("Угадай число: ", end="") Input = int(input()) Attempt + 1 if Input < Case : print("Слишком маленькое!") if Input > Case : print("Слишком большое!") if Input == Case : print("Правильно!") В основе функции playGame() лежит цикл, который гаранти- рует, что игра продолжается до тех пор, пока ты не угада- ешь число. Как видишь, я использовал здесь упрощенную версию, где ты не сможешь просто взять и завершить игру в любой момент. И поэтому для последней функции остает- ся только одна строка: def endGame() : print("Ты попробовал " + str(Attempt) + " раз.") Наконец, все три функции должны сработать, это и называ- ется основной программой, которая здесь довольно неболь- шая: Глава Функции 5 98 # Основная программа initGame() playGame() endGame() ¾ Итак, теперь твоя очередь. Возможно, тебе будет удоб- нее и проще создать новый проект. Необходимо убе- диться, что функции определены. Как считаешь, у тебя получится? Если нет, позже я приведу код целиком. Локальные или глобальные переменные? Если твоя программа внезапно завершается с сообщением об ошибке, это происходит не из-за тебя, а из-за того, что с переменными что-то не так. Рис. 5.2.Ошибка из-за недоступности переменных По-видимому, функция playGame() не может ничего сделать с переменной Input. Хотя она использовалась ранее в функ- ции initGame(), она должен быть знакома твоему компьюте- ру. Что же происходит не так? Дело в том, что в первую очередь все переменные будут действительны только там, где они были объявлены. В по- следних версиях игры переменные были действительны для всей основной программы. А основной программой был исходный код целиком. Локальные или глобальные переменные? 99 Теперь же код выглядит так: сначала указывается несколько определений, а далее приводится код основной програм- мы. И как я только что обьяснил, переменные действуют только в той функции, в которой используются. Это также означает, что могут существовать две разные переменные с одним и тем же именем и одна из них работает в функции initGame() , а другая – только в playGame(). Все переменные, которые были определены в пределах ка- кой-либо функции, действуют только в ней – с точки зрения об- щей программы, которая может состоять из множества функций, это локальные переменные. После выхода из функции локальные переменные станут недо- ступны. Но поскольку нам нужны переменные, которые будут доступны повсюду, поэтому во всех наших функциях у нас есть возможность сделать их глобальными. И как мы достигнем подобной «глобализации»? Это проще обьяснить, если ты посмотришь на исходный код целиком (⇒ guess7): import random # Функции def initGame() : global Attempt, Input Secret = "Я задумал число от 1 до 1000" print(Secret) Attempt = 0 Input = 0 def playGame() : global Attempt, Input Case = random.randint(1,1000) # print(Case) while Input != Case : print("Угадай число: ", end="") Input = int(input()) Attempt += 1 if Input < Case : print("Слишком маленькое!") if Input > Case : print("Слишком большое!") if Input == Case : print("Правильно!") def endGame() : Глава Функции 5 100 global Attempt print("Ты попробовал " + str(Attempt) + " раз.") # Основная программа initGame() playGame() endGame() Вероятно, ты заметил эти дополнительные строки. Так: global Attempt, Input мы также сообщаем соответствующей функции о том, что одна или несколько переменных должны быть доступны глобально, то есть никакая новая переменная с этим име- нем не должна создаваться внутри функции. Таким обра- зом, в обеих функциях могут использоваться те же пере- менные Attempt и Input. Переменная должна объявляться на глобальном уровне, если ее значение должно быть изменено. Функция endGame() не меняет значение переменной, а лишь считывает ее. Таким образом, ты также можешь опустить для нее инструкцию global. ¾ Теперь проверь, что твой исходный код выглядит так, как листинг выше, сохрани все изменения и запусти игру. Попробуй запустить ее несколько раз. На самом деле все должно работать как в последней версии этой игры-загадки. Новое здесь то, что переменные были объявлены в глобальной области видимости. Параметры Если бы ты объявил все переменные, которые встречают- ся в программе, глобально, то у тебя всегда был бы доступ к ним. Но имеет ли это смысл? Представь, что ты работаешь над колоссальным проектом, большим приложением или серьезной игрой. В таком проекте огромное количество пе- ременных: десятки, сотни и даже свыше тысячи. Зачем же нам доступность этих переменных во всей про- грамме, если большинство из них необходимо только в определенных ее частях? Если бы все переменные были глобальными, произошло бы наверняка и такое, что вне- Параметры 101 запно их значения изменились бы, чего на самом деле быть не должно. А вот найти эту ошибку, а тем более исправить ее, в большом количестве исходного кода быстро не полу- чится. Не было бы лучшим решением этой проблемы всегда ис- пользовать переменную именно там, где она будет нужна? Давай взглянем на наш текущий проект: Переменная Используется в: Secret initGame() Case playGame() Input initGame(), playGame() Attempt initGame(), playGame(), endGame() Для всех функций требуется только одна из переменных. Еще две, Secret и Case, используются локально. Но локальным переменным все же присущи проблемы, не так ли? Они усложняют программу, особенно когда проект становится все больше и больше. А как теперь вызвать функции с применением переменных Attempt и Input? Для этого ведь нужны круглые скобки? Зна- чит, они не должны оставаться пустыми. Представь себе, что скобки – это руки, которыми функция «обнимает» параметры. Термин параметр мы уже рассмат- ривали с тобой в предыдущей главе. БлокИнструкций ИмяФункции Параметры def ( ) : Когда функция получает имена переменных в качестве па- раметров, она может сделать с ней некое действие. Напри- мер, вот так: def initGame(Attempt, Input) : def playGame(Attempt, Input) : def endGame(Attempt) : В основной программе первая из трех функций может быть вызвана с числовыми значениями в качестве параметров, например так: Глава Функции 5 102 initGame(0,0) Таким образом, внутри функции переменные Attempt и In put будут иметь значение 0. И тогда эти присваивания боль- ше не нужны: Attempt = 0 Input = 0 Теперь ты можешь забыть про них. Да, и еще кое-что: здесь нам не нужны какие-либо параметры, поэтому функция может быть сокращена следующим образом: def initGame() : Secret = "Я задумал число от 1 до 1000" print(Secret) Но как мы теперь присвоим переменным Attempt и Input значение 0? Передав два нуля в качестве параметров при вызове следующей функции: playGame(0,0) Внутри себя функция теперь может продолжать использо- вать эти две переменные. И поэтому код нашей функции playGame() может выглядеть так: def playGame(Attempt, Input) : Case = random.randint(1,1000) while Input != Case : print("Угадай число: ", end="") Input = int(input()) Attempt += 1 if Input < Case : print("Слишком маленькое!") if Input > Case : print("Слишком большое!") if Input == Case : print("Правильно!") Ввод известен перед переходом к строке конструкции while. И значение переменной Attempt будут рассчитываться соот- ветствующим образом, исходя из начального 0. Параметры 103 Как видишь, в обоих определениях функций инструкции global не используются. Теперь нам нужен параметр для последней функции, по- скольку мы не можем просто передать ей фиксированное значение: endGame(10) Текущее значение переменной Attempt должно быть пере- дано после того, как вы поиграли и число увеличилось. Но это работает, только если это значение каким-то образом покидает функцию playGame(). В языке Python есть решение этой проблемы. Инструкция return используется для воз- врата из функции, т. е. для прекращения ее работы и выхо- да из нее. return Attempt Инструкция return должна находиться в последней строке определения функции playGame(). Эта функция может быть вызвана двумя способами: playGame(0,0) Game = playGame(0,0) Во втором варианте сама функция назначается (новой) пе- ременной (которую я назвал Game). Так мы получаем значе- ние, которое возвращает функция с помощью инструкции return Поэтому функции могут использоваться двумя различными способами: как простая инструкция или как присвоение: Функция Переменная Переменная Функция () = Функция() (Параметр) = Функция(Параметр) Переменная, которая приняла значение функции, теперь может служить параметром для следующей функции: endGame(Game) Глава Функции 5 104 Вот полный листинг исходного кода программы (⇒ guess8.py): import random # Функция def initGame() : Secret = "Я задумал число от 1 до 1000" print(Secret) def playGame(Attempt, Input) : Case = random.randint(1,1000) # print(Case) while Input != Case : print("Угадай число: ", end="") Input = int(input()) Attempt += 1 if Input < Case : print("Слишком маленькое!") if Input > Case : print("Слишком большое!") if Input == Case : print("Правильно!") return Attempt def endGame(Attempt) : print("Ты попробовал " + str(Attempt) + " раз.") # Основная программа initGame() Game = playGame(0,0) endGame(Game) ¾ Введи исходный код и запусти свою программу. Полу- чилось ли угадать число, и сколько в итоге вышло по- пыток? Если игра работает, то ты сделал все правильно! Обмен значений Продолжая работу с функциями, давай рассмотрим новый пример их использования. Он относится к числам, но не очень тесно связан с математикой. Попробуем поменять местами два значения – например, когда необходима сор- тировка данных. Как же произойдет обмен? Представь, что у тебя обе руки заняты, например, бутылками газировки. Теперь поменяй бутылки в руках! Обмен значений 105 Скорее всего, у тебя ничего не получится. Хотя можно по- пробовать подбросить бутылки в воздух и заменить их таким образом. Или разбить. Для программирования это в любом случае было бы слишком рискованно. Поэтому для обмена значений двух переменных необходи- ма еще одна вспомогательная переменная, чтобы ничего не пошло наперекос. Назовем переменные, значения которых необходимо об- менять, Number1 и Number2 и присвоим вспомогательной пе- ременной имя Swap. Процесс обмена будет выглядеть так: Swap = x1 x1 = x2 x2 = Swap Поместим код в функцию и сразу же ее вызовем. Поскольку я буду использовать переменные с именами Num ber1 и Number2 в основной программе (а также как парамет- ры), я сокращу их имена: x1 и x2. Теперь давай посмотрим, как все это может выглядеть в полном коде программы (⇒ swap1.py): def exchange(x1, x2) : Swap = x1 x1 = x2 x2 = Swap # Основная программа print("Введи число: ", end="") Number1 = int(input()) print("И еще одно : ", end="") Number2 = int(input()) print ("До обмена: " + str(Number1) + " и " + str(Number2)) exchange(Number1, Number2) print("После обмена: " + str(Number1) + " и " + str(Number2)) В основной программе вводятся первые два числа, и они отображаются в правильном порядке. Затем они меняют- ся местами, это делается в строке exchange(Number1, Number2), и, наконец, числа в итоге будут отображаться в обратном порядке (рис. 5.3). |