§ 9.2. Процедуры и функции

Школьный курс C++
Содержание

Для чего нужны подпрограммы?

В различных примерах программ мы обращали ваше внимание на повторяющийся код, который значительно увеличивал объем этих программ. Для оптимизации программного кода, чтобы сделать его более понятным и удобным для восприятия, используются подпрограммы. Подпрограмма (англ. subroutine) позволяет вынести часть реализации (некоторую вполне самостоятельную подзадачу или алгоритм) за пределы основной программы и обращаться к ней, по мере необходимости, по имени, из любой части программы. Таким образом, можно не только сократить программный код, но и сделать его более структурированным.
Существует две разновидности подпрограмм: процедуры и функции. В отличие от процедур, функции всегда возвращают результат в точку вызова. Но это деление чисто условное. В Python между функциями и процедурами нет больших синтаксических различий.

Фактически, даже если функция не имеет инструкции return, она все равно возвращают значение. Это значение равно None. Значение None подавляется интерпретатором, если это единственное возвращенное значение.

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

Определение функции. Ключевое слово def

Для определения (англ. definition) функции используется ключевое слово def. Непосредственно после def указывается имя функции и круглые скобки. В скобках перечисляются так называемые формальные параметры или просто параметры. Эта часть определения называется заголовком функции. После заголовка, на следующей строке, следует блок тела функции.
Синтаксически это выглядит следующим образом:

def имя_функции(список_параметров):
    Тело_функции
    [return Выражение_возвращаемого_значения]

Параметры – это локальные переменные функции, которые инициализируются в момент вызова функции в основной программе (см. ниже). Помимо параметров, в функции могут быть и другие локальные переменные. Если функция не имеет параметров (т. е. данные в функцию не принимаются из-вне), то круглые скобки остаются пустыми. Приведем пример такой функции.

def line():
    print('------------------------------')

Если вызвать эту функцию

line()

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

Вызов функции

В основной программе функция вызывается по имени (стр. 11 в программе 9.2.1). Если в функции определены параметры, то после имени функции, в круглых скобках, перечисляются фактические параметры или аргументы. Аргументы функции являются инициализаторами параметров. При этом, количество аргументов должно соответствовать количеству параметров функции. Переделаем функцию так, чтобы она содержала три параметра определяющих количество выводимых линий, их длину и используемый символ. Тогда программу полностью мы можем записать так:
Задача 1. Вывести на экране n линий длиною d с помощью символа ch.

Программа 9.2.1
def line(n, d, ch):
    for i in range(n):
        for j in range(d):
            print(ch, end='')
        print()
    
n = int(input('Количество линий => '))
d = int(input('Длина линий => '))
ch = input('Символ => ')

line(n, d, ch)

Вывод

Количество линий => 5
Длина линий => 20
Символ => ~
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~

Процедуры

Тип функции описанной в программе 9.2.1 – это процедура. Процедура производит определенные действия в программе, но не возвращает никакого значения. Вызов процедуры можно включать в программу отдельной инструкцией в основной программе, в ветвях условной инструкции, в теле цикла, а также в других функциях.
В программе 9.1.9, которую мы написали на предыдущем уроке, содержался многократно повторяющийся код рисования треугольника:

t.fillcolor("Имя_цвета")        
t.begin_fill()
    for i in range(3):            
        t.fd(k)            
        t.rt(120)        
t.end_fill()

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

Программа 9.2.2
import turtle as t
from math import sqrt
##################### Параметры холста ######################
w = t.Screen()
w.reset()
w.title('Плитка')
w.bgcolor('black')
w.setup(width = 600, height = 600, startx = -10, starty = 10)
#################### Параметры черепахи #####################
t.speed(10)
t.hideturtle()
t.goto(-300,300)
###################### Решение задачи #######################
def tri(k, color):
    t.fillcolor(color)        
    t.begin_fill()
    for i in range(3):            
        t.fd(k)            
        t.rt(120)        
    t.end_fill()
    
d = int(input("Длина стороны -> "))
n = 600 // d # Определяем количество плиток
m = 600 // int(d * sqrt(3)) # количество рядов
for i in range(m + 1):    
    for j in range(n + 1):  # за один шаг рисуем 2 ряда
        tri(d, "DeepSkyBlue4")    
        t.rt(60)
        tri(d, "dark turquoise")
        t.fd(d)
        tri(d, "dark turquoise")
        t.rt(60)
        tri(d, "DeepSkyBlue4")
        t.lt(180)
        t.fd(d)
        t.rt(60)
    t.bk((n + 1) * d) # Перемещаемся к следующему ряду  
    t.rt(120)    
    t.fd(d)    
    t.lt(60)
    t.fd(d)
    t.lt(60)
w.exitonclick()
t.mainloop()

Наша программа сократилась на 14 строк! Обратите внимание, что аргументами функции могут быть не только переменные, но и константы. Так, в этой программе, значение цвета передается строковым литералом.

Функции. Инструкция return

Подпрограмма, которая возвращает определенное значение в точку вызова называется функцией. Из этого следует, что функция должна быть операндом выражения, в которое она возвращает своё значение. Например, выражение с присваиванием значения функции переменной:

a = myFun()

или возвращение значения функции при вызове другой функции (т. е. использование функции в качестве аргумента):

print(myFun())

Чтобы функция смогла возвращать какое-либо значение полученное в процессе её работы используется инструкция return. Эта инструкция завершает работу функции и возвращает ее значение выражением, которое следует за ключевым словом return. В теле функции должна быть только одна такая инструкция. Допускается использование нескольких инструкций return, но только в том случае, если они находятся в ветвях условной инструкции.
Задача 2. Составить программу вычисляющую среднее арифметическое и среднее геометрическое двух введенных чисел a и b. Вычисление среднего арифметического и среднего геометрического оформить в виде функций.

Программа 9.2.3
def amean(a, b):
    return (a + b) / 2

def gmean(a, b):
    return (a * b) ** 0.5

a = float(input('a = '))
b = float(input('b = '))
print('Среднее арифметическое {:} и {:} = {:.3}'
      .format(a, b, amean(a, b)))
print('Среднее геометрическое {:} и {:} = {:.3}'
      .format(a, b, gmean(a, b)))

Вывод

a = 2
b = 7
Среднее арифметическое 2.0 и 7.0 = 4.5
Среднее геометрическое 2.0 и 7.0 = 3.74

Функция может возвращать любое значение, в том числе логическое. Используем ранее составленную программу (8.9.9) для решения следующей задачи с помощью логической функции.
Задача 3. Составить программу определяющую является ли число простым. Тест на простоту оформить в виде функции.

Программа 9.2.4
def prime(n):
    i = 2
    f = True
    while i <= n // 2:
        if n % i == 0:
            f = False
            break
        else: 
            i += 1
    return f

n = int(input('n = '))
if prime(n):
    print('Это число простое')
else: 
    print('Число не является простым')

Вывод

n = 100
Число не является простым
---------------------
n = 101
Это число простое

Локальные и глобальные переменные

Ранее мы упоминали, что блок функции определяет область видимости данных. Что это значит? Приведем пример:

Программа 9.2.5
a = 2          # Глобальная переменная
def fun(a):    # Параметр — локальная переменная
    a = 10 * a # Изменение локальной переменной
    print('local  a =', a)
fun(a)                 # аргумент - глобальная переменная
print('global a =', a) # значение переменной а не изменилось

Вывод

local  a = 20
global a = 2

Параметр a функции fun является локальной переменной – её видимость определяется блоком функции, поэтому значение глобального объекта a не изменится после вызова функции.
Вызов функции вводит в программу новую таблицу имен для локальных переменных. Сначала просматриваются ссылки на локальные объекты в локальной таблице имен, затем в локальных таблицах имен включаемых функций (это следует учитывать, если в данной функции вызываются другие функции), затем в глобальной таблице имен и, наконец, в таблице встроенных имен. Таким образом, глобальным переменным и переменным включаемых функций нельзя напрямую присвоить значение внутри функции (за исключением тех случаев, когда для глобальных переменных используется инструкция global, а для переменных включаемых функций используется инструкция nonlocal), хотя ссылаться на них можно. Поэтому функция fun изменяет значение локальной перемененной a, но не изменяет глобальный объект a.
По этой же причине нельзя составить функцию обмена значениями между двумя переменными так, как показано в программе ниже:

Программа 9.2.6
a = int(input('a = '))
b = int(input('b = '))

def Swap(a, b):
    a, b = b, a

print('a = ', a)
print('b = ', b)

Тем не менее, есть множество вариантов выполнить эту задачу по другому. Например, возвращать кортеж (пару), в котором будет изменен порядок следования элементов, как в программе ниже.
Задача 4. Составить программу в которой используется функция обмена значениями между двумя перменными.

Программа 9.2.7
a = int(input('a = '))
b = int(input('b = '))

def Swap(a, b):
    return (b, a)

a, b = Swap(a, b)

print('a =', a)
print('b =', b)

Вывод

a = 2
b = 5
a = 5
b = 2

Выше мы применяли одни и теже имена как для глобальных, так и для локальных объектов. Но, во избежании путаницы, для локальных имен функций лучше применять другие имена.
Программу 9.2.6 легко исправить, если в функции Swap использовать инструкцию global, которая связывает локальное имя с глобальным объектом. Тогда код функции можно переписать следующим образом:

def Swap(x, y):
    global a, b
    a, b = y, x

Вынос различных подзадач в функции значительно упрощает чтение и обзор основной программы. Покажем это на следующей задаче.
Задача 5. Составить программу подсчета всех шестизначных счастливых “чисел”. Число называется “счастливым”, если сумма его первых трех разрядов равна сумме трех его младших разрядов.

Программа 9.2.8
def threefirst(n):
    return n // 1000 % 10 + \
           n // 10000 % 10 + \
           n // 100000

def threelast(n):
    return n % 10 + \
           n // 10 % 10 + \
           n // 100 % 10

def res(n):
    return threefirst(n) == threelast(n)

i = 0
for j in range(100000, 1000000):
    if res(j): i += 1
else:
    print(i)

Вывод

50412

Приложение

Примеры решения задач
Вопросы
Темы сообщений
Задания А
Задания Б
Задания С
Ссылки
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Обсуждение закрыто.