Программирование аркадных игр и обучение информатике

Программирование аркадных игр
и обучение информатике

Chapter 9: Функции

9.1 Введение в функции

Видео: Зачем использовать функции?

Функции используются в языках программирования по двум основным причинам. Первая: они делают код более понятнее и читабельнее. Второе - они позволяют использовать один и тот же код более одного раза.

Представьте себе набор кода, который способен контролировать игрушечную машинку. На самом деле, такая машинка и послужила автору представлением программирования в 1979: http://ru.wikipedia.org/wiki/Big_Trak

Предположим, программист пожелает, чтобы машина двигалась вперёд. Чтобы это сделать, программист может пожелать выполнить следующие команды:

turnOnMotor() #включить мотор
pauseOneSecond() #подождать 1 секунду
turnOffMotor() #выключить мотор

Этот код не так просто понять. Объявляя функцию, мы можем улучшить читаемость кода и позволить программисту использовать его несколько раз. Дефиниция функции в Python выглядит так:

def moveForward(): #двигаться вперёд
  turnOnMotor() #включить мотор
  pauseOneSecond() #подождать 1 секунду
  turnOffMotor() #выключить мотор

Сам по себе, этот код ничего не сделает. Его запуск не заставит машину двигаться вперёд. Он говорит компьютеру как это сделать. Так что после описания тела функции, программе нужно сделать следующее для запуска машины:

moveForward()

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

moveForward()
turnLeft()
moveForward()
moveForward()
turnRight()
moveForward()

Функции также могут получать параметры. Они могут быть использованы для увеличения приспособляемости функций, варьируя её действия в зависимости от переданного параметра. Например, функция с названием jump() может заставить робота прыгнуть. Но функция также может быть изменена, прося параметр, определяющий, как выосоко должен прыгнуть робот. Например jump(3) заставит робота прыгнуть на три дюйма, а jump(6) - на 6.

Функция движения могла бы выглядеть следующим образом:

def moveForward(time):
	turnOnMotor()
	for i in range(time):
		pauseOneSecond()
	turnOffMotor()

Пример такой функции, не требующей машины-робота, мог бы быть следующим:

def volumeSphere(radius):
    pi=3.141592653589
    volume=4*pi*radius**2
    print("The volume is",volume)

Видео: создание функции

В вышеприведённой функции, программист вызывал функцию volumeSphere. Данные, передаваемые в функцию, храняться в переменной под названием radius. Объём, полученный в результате, выводится на экран. Чтобы вызвать эту функцию, нужно написать:

volumeSphere(22)

В функцию может быть передано несколько параметров, отделённых запятыми:

def volumeCylinder(radius,height):
    pi=3.141592653589
    volume=2*pi*radius*(radius+height)
    print("The volume is",volume)

Эта функция может быть вызвана с помощью:

volumeCylinder(12,3)

Однако, у этих функция ограниченное использование. Если человеку потребовалось бы использовать функцию volumeCylinder для вычисления объёма шести цилиндров, она бы не сработала. Она лишь выводит один объём. Нет возможности взять результат и использовать его в уравнении, умножив на шесть.

Это можно решить с помощью выражения return. Например:

def volumeCylinder(radius,height):
    pi=3.141592653589
    volume=2*pi*radius*(radius+height)
    return volume

Это может быть использовано в дальнейшем коде вроде этого:

sixPackVolume = volumeCylinder(2.5,5) * 6

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

# Функция, выводящая результат
def sum1(a,b):
    result = a+b
    print (result)

# Функция, возвращающая результат
def sum2(a,b):
    result = a+b
    return (result)

# Это выведет сумму 4+4
sum1(4,4)

# Это не выведет ничего
sum2(4,4)

# Это не приравняет x1 к сумме
x1 = sum1(4,4)

# Это приравняет x2 к 4+4
x2 = sum2(4,4)

9.2 Видимость переменных

Видео: видимость переменных

Использование функций представляет нам концепцию видимости. Видимость обозначает, в каких местах кода переменная “жива” и доступна к использованию. Например, посмотрите следующий код:

# Объявить простую функцию, которая приравнивает
# x к 22
def f():
    x=22

# Вызвать функцию
f()
# Это не сработает, потому что x существует только внутри f()
print (x)

Последняя строка покажет ошибку, потому что x существует только внутри функции f(). Переменная создаётся когда вызывается f(), так что используемая ею память освобождается в тот момент, когда заканчивается действие самой f().

Ещё более вводящими в заблуждение являются переменные, созданые вне функции f() В следующем коде, x создаётся перед функцией f(), тем самым позволяя ему быть считанным внутри самой функции f().

# Создать переменную x и присвоить ей 44
x=44

# Задать простую функцию, выводящую x
def f():
    print(x)

# Вызвать функцию
f()

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

# Создать переменную x и присвоить ей 44
x=44

# Задать простую функцию, выводящую x
def f():
    x += 1
    print(x)

# Вызвать функцию
f()

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

9.3 Передать как копию

Функции хранят переданные им аргументы копируя значение оригинала и храня его отдельно. Например:

# Задать простую функцию, выводящую x
def f(x):
    x += 1
    print(x)

# Задать y
y=10
# Вызвать функцию
f(y)
# Вывести y, чтобы проверить, изменилось ли его значение
print(y)

Значение y не меняется, даже несмотря на то, что функцияd f() увеличивает переданное ей значение. Каждая из переменных, указанная как параметр функции, по сути является совершенно новой переменной, в которую копируется значение переменной, передающейся функции как аргумент.

Это достаточно очевидно в предыдущем примере. Однако, вещи становятся более запутанными, если код, из которого вызывается функция, а также код самой функции, содержат одноименные переменные. Нижеприведённый код идентичен предыдущему, однако вместо того, чтобы использовать y, он использует x.

# Задать простую функцию, выводящую x
def f(x):
    x += 1
    print(x)

# Задать x
x=10
# Вызвать функцию
f()
# Вывести x, чтобы узнать, изменился ли он
print(x)

Вывод такой же, как и у программы, испольщующей y. Несмотря на то, что как начальный код, так и внутренности функции используют x как имя переменной, на самом деле существуют две разные переменные. Переменная x, существующая внутри функции и другая переменная x, существующая вне функции.

9.4 Функции, вызывающие функции

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

def armOut(whichArm, palmUpOrDown): #вытянуть руку
	# здесь будет код
def handGrab(what): #ухватиться
	# здесь будет код

Затем может быть создана другая функция, вызывающая функции, описанные ранее:

def macarena():
	armOut("right","down")
	armOut("left","down")
	armOut("right","up")
	armOut("left","up")
	handGrab("right","left arm")
	handGrab("left","right arm")
	# и так далее

9.5 Повторение пройденного

Пройдите тест с несколькими вариантами ответов (на англ. яз.).

Эти проверочные вопросы также могут быть скачаны как DOCX документ MS Word 2010.

9.5.1 Предсказывание вывода

Попробуйте предсказать, что выведет каждый из блоков кода:

  1. Block 1
    for i in range(5):
        print (i+1)
    
  2. Block 2
    for i in range(5):
        print (i)
        i=i+1
    
  3. Block 3
    x=0
    for i in range(5):
        x+=1
    print (x)
    
  4. Block 4
    x=0
    for i in range(5):
        for j in range(5):
            x+=1
    print (x)        
    
  5. Block 5
    for i in range(5):
        for j in range(5):
            print (i,j)
    
  6. Block 6
    for i in range(5):
        for j in range(5):
            print ("*",end="")
            print ()
    
  7. Block 7
    for i in range(5):
        for j in range(5):
            print ("*",end="")
        print ()
    
  8. Block 8
    for i in range(5):
        for j in range(5):
            print ("*",end="")
    print ()
    
  9. Block 9
    # В чём здесь ошибка?
    array=[5,8,10,4,5]
    i=0
    for i in array:
        i = i + array[i]
    print(i)
    
  10. Block 10
    for i in range(5):
        x=0
        for j in range(5):
            x+=1
    print (x)
    
  11. Block 11
    import random
    play_again="y"
    while play_again=="y":
        for i in range(5):
            print (random.randrange(2),end="")
        print ()
        play_again=input("Play again? ")
    print ("Bye!")
    
  12. Block 12
    def f1(x):
        print (x)
    y=3
    f1(y)
    
  13. Block 13
    def f2(x):
        x=x+1
        print (x)
    y=3
    f2(y)
    print (y)
    
  14. Block 14
    def f3(x):
        x=x+1
        print (x)
    x=3
    f3(x)
    print (x)
    
  15. Block 15
    def f4(x):
        z=x+1
        print (z)
    x=3
    f4(x)
    print (z)
    
  16. Block 16
    def foo(x):
        x=x+1
        print ("x=",x)
    
    x=10
    print ("x=",x)
    foo(x)
    print ("x=",x)
    
  17. Block 17
    def f():
        print ("f start")
        g()
        h()
        print ("f end")
    
    def g():
        print ("g start")
        h()
        print ("g end")
        
    def h():
        print ("h")
        
    f()
    
  18. Block 18
    def foo():
        x=3
        print ("foo has been called")
        
    x=10
    print ("x=",x)
    foo()
    print ("x=",x)
    
  19. Block 19 (Это демонстрирует новую концепцию, которая не будет полностью объяснена до 13й главы.)
    def a(x):
        print ("a",x)
        x=x+1
        print ("a",x)
        
    x=1
    print ("main",x)
    a(x)
    print ("main",x)
    
    def b(y):
        print ("b",y[1])
        y[1]=y[1]+1
        print ("b",y[1])
        
    y=[123,5]
    print ("main",y[1])
    b(y)
    print ("main",y[1])
    
    def c(y):
        print ("c",y[1])
        y=[101,102]
        print ("c",y[1])
        
    y=[123,5]
    print ("main",y[1])
    c(y)
    print ("main",y[1])
    

Видео: Объяснение блоков кода

Если какой-либо из решений этих задач не ясен, проверьте видео, приведённое справа. Каждый номер блока написан в верхнем комментарии, так что вы можете перескочить к интересующему вас фрагменту.

9.5.2 Исправление кода

  1. Исправьте следующий код: (Не давайте ему вывести слово “None”)
    def sum(a,b,c):
        print (a+b+c)
    
    print (sum(10,11,12))
    
  2. Исправьте следующий код: (x должен увеличиваться на один, но этого не происходит.)
    
    def increase(x):
        return x+1
    
    x=10
    print ("X is",x," I will now increase x." )
    increase(x)
    print ("X is now",x)
    
  3. Исправьте следующий код:
    def print_hello:
        print ("Hello")
    
    print_hello()
    
  4. Исправьте следующий код:
    def count_to_ten():
        for i in range[10]:
            print (i)
    
    count_to_ten()
    
  5. Исправьте следующий код:
    def sum_list(list):
        for i in list:
            sum=i
            return sum
    
    list=[45,2,10,-5,100]
    print (sum_list(list))
    
  6. Исправьте следующий код: (Это почти переворачивает строку. Что случилось?)
    def reverse(text):
        result=""
        text_length=len(text)
        for i in range(text_length):
            result=result+text[i*-1]
        return result
    
    text="Programming is the coolest thing ever."
    print (reverse(text))
    
  7. Исправьте следующий код:
    def get_user_choice():
        while True:
            command=input("Command: ")
            if command=f or command=m or command=s or command=d or command=q:
                return command
            
            print ("Hey, that's not a command. Here are your options:" )
            print ("f - Full speed ahead")
            print ("m - Moderate speed")
            print ("s - Status")
            print ("d - Drink")
            print ("q - Quit")
    
    user_command=get_user_choice()
    print ("You entered:",user_command)
    

Видео: Объяснения, как исправить код

Для объяснений по исправлению кода, посмотрите видео справа. Не смотрите видео до тех пор, пока вы не потратили достаточно времени на размышления о исправлении кода, иначе всё это будет бессмысленным.

9.6 Написание кода

  1. Напишите функцию, выводящую “Hello World.”
  2. Напишите код, вызывающую функцию в задании 1.
  3. Напишите функцию, выводящую, например “Hello Bob”, требующую имя как параметр. Не пишите input внутри функции! Используйте параметр.
  4. Напишите код, вызывающий функцию из задания 3.
  5. Напишите функцию, которая будет брать два числа как параметры (не ввод от пользователя) и выводить их произведение, умножив их.
  6. Написать код, вызывающий предыдущую функцию.
  7. Написать функцию, берущую два параметра. Первым параметром будет строка под названием phrase. Вторым параметром будет число под названием count. Вывести phrase на экран count раз. (Например, функция берёт "Hello" и 5, затем выводит "Hello" пять раз.)
  8. Написать код, вызывающим предыдущую функцию.
  9. Написать код для функции, берущей число и возвращающей квадрат этого числа. Заметьте, что функция должна возвращать, но не выводить, ответ.
  10. Написать код, вызывающий предыдущую функцию.
  11. Написать функцию, берущую три числа в виде параметров, и возвращающую центробежную силу. Формула центрабежной силы:
    $F=mr\omega^2$
    $F$ - сила, $r$ - радиус, $\omega$ - угловая скорость, $m$ - масса.
  12. Написать код, вызывающий вышеприведённую функцию.
  13. Написать функцию, берущую список как параметр и выводящую на экран каждый номер по отдельности, используя цикл “for”.

Видео: написание кода

Вот ответы. Но не смотрите видео до тех пор, пока вы не провели достаточно времени над попытками написать правильный код.


You are not logged in. Log in here and track your progress.