Глава 13 · Автоматизация с помощью функций

Мини-проект — Turtle Function Studio

Фигуры из глав 6 и 10 становятся настоящей переиспользуемой функцией с явными параметрами — и подводим итоги всей главы о функциях.

Используем
defпараметрыциклыTurtle
Уровень
★★★★ challenge
Результат
графика Turtle

Что создаём

Финальный проект главы: превратим повторяющийся код рисования фигур из глав 6 и 10 в настоящую переиспользуемую функцию с параметрами.

Поток данных функции

ВЫЗОВdraw_polygon(artist,6, 80)ПАРАМЕТРЫartist, sides=6,length=80РАСЧЁТangle = 360 / sidesЦИКЛsides разРЕАЛЬНЫЙ ВЫВОДшестиугольник
Один вызов — параметры разворачиваются в расчёт, цикл и итоговый рисунок
draw_polygon.py
import turtle

screen = turtle.Screen()
screen.setup(width=300, height=300)
artist = turtle.Turtle()
artist.speed(0)
artist.pencolor("#5B24F9")
artist.pensize(3)

def draw_polygon(artist, sides, length):
    angle = 360 / sides
    for _ in range(sides):
        artist.forward(length)
        artist.right(angle)

draw_polygon(artist, 6, 80)

screen.exitonclick()
Результат выполнения
Правильный шестиугольник, нарисованный функцией draw_polygon
draw_polygon(artist, 6, 80) — правильный шестиугольник

Почему функция принимает artist явно

figura_funkciya.py
def draw_polygon(artist, sides, length):
    angle = 360 / sides
    for _ in range(sides):
        artist.forward(length)
        artist.right(angle)

draw_polygon(artist, 4, 100)    # квадрат
draw_polygon(artist, 3, 100)    # треугольник, без повторения кода!
draw_polygon(artist, 8, 60)     # восьмиугольник
Явный параметр artist — не лишняя формальность
Функция могла бы полагаться на глобальную переменную artist, как в главе 10. Но параметр делает зависимость ЯВНОЙ (§13.15): сразу видно, что функция работает именно с той черепашкой, которую ей передали, — её можно переиспользовать с другой черепашкой (например, во время гонки Turtle из §12.6, где черепашек несколько) без единого изменения кода внутри.

Функция внутри цикла: то же поведение, новый параметр на каждом шаге

figury_v_cikle.py
cveta = ["#5B24F9", "#DB2777", "#059669"]
for i, sides in enumerate(range(3, 9)):
    artist.pencolor(cveta[i % 3])
    draw_polygon(artist, sides, 70)
    artist.right(15)
figury_v_cikle.py
import turtle

screen = turtle.Screen()
screen.setup(width=420, height=420)
artist = turtle.Turtle()
artist.speed(0)
artist.pensize(2)

def draw_polygon(artist, sides, length):
    angle = 360 / sides
    for _ in range(sides):
        artist.forward(length)
        artist.right(angle)

cveta = ["#5B24F9", "#DB2777", "#059669"]
for i, sides in enumerate(range(3, 9)):
    artist.pencolor(cveta[i % 3])
    draw_polygon(artist, sides, 70)
    artist.right(15)

screen.exitonclick()
Результат выполнения
Веер из шести повёрнутых многоугольников от треугольника до восьмиугольника, нарисованный циклом, вызывающим draw_polygon
Цикл вызывает draw_polygon с новым sides на каждом шаге — веер многоугольников
Цикл автоматизирует повторение, функция — поведение
Ровно идея §13.1: цикл решает, СКОЛЬКО раз и с какими данными вызвать draw_polygon; сама функция решает, КАК нарисовать многоугольник с этими данными. Ни один из двух инструментов не заменяет другой.
★★★ Задача повышенной сложности
Функция с позицией

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

Практика: Turtle Function Studio
Модуль turtle открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально
Открыть практику →

Итоги главы

Инструментарий проектирования функции

Итоговый инструментарий главы 13
Нужно повторно использовать один и тот же набор действий?
выделите функцию
Функции нужны входные данные?
параметры
Нужно вернуть результат для дальнейшего использования?
return
Аргументов может быть неизвестное количество?
*args / **kwargs
Некоторые аргументы стоит сделать необязательными?
значения по умолчанию (не изменяемые!)
Некоторые аргументы должны передаваться только по имени?
keyword-only, после *
Функция должна вести себя предсказуемо и легко тестироваться?
чистая функция, без побочных эффектов
Нужно передать саму функцию как значение?
функция — объект первого класса
Нужно крошечное правило для sorted()/max()?
lambda
Полный чек-лист проектирования — в §13.18

Что мы узнали в этой главе

  • Функция — именованный переиспользуемый кусок поведения: получает данные (параметры), работает с ними, возвращает результат (return).
  • Вызов функции передаёт управление в её тело и обязательно возвращается к месту вызова — функция не выполняется «где-то в стороне».
  • Параметр — имя в определении, аргумент — значение в вызове. Присваивание параметру и мутация переданного объекта — два разных действия с разными последствиями снаружи.
  • Изменяемое значение по умолчанию создаётся ОДИН РАЗ при определении функции — используйте None как сигнальное значение вместо [] или {}.
  • *args и **kwargs собирают лишние аргументы в кортеж и словарь соответственно; та же */** на месте вызова распаковывает коллекцию обратно.
  • Функция без return всё равно возвращает None — это не «ничего», а конкретный объект.
  • Python ищет имя по правилу LEGB: Local → Enclosing → Global → Builtins.
  • Функции, вызывающие функции, образуют стек вызовов — и traceback из главы 3 показывает именно этот стек в момент ошибки.
  • Функции — объекты первого класса: их можно сохранять под другим именем, класть в коллекции, передавать другим функциям (sorted(key=...)).
  • lambda — маленькая безымянная функция для одного выражения, не более «современная» замена def.
  • Рефакторинг большого скрипта в набор функций делает главную программу читаемым описанием алгоритма, а каждую часть — независимо тестируемой.

Что дальше

Мы научились группировать ПОВЕДЕНИЕ в функции. Но во многих наших проектах данные и поведение, которое с ними работает, естественно ходят парой — контакт со своим телефоном, ученик со своим баллом, черепашка со своим цветом и позицией. В следующей главе — «Создаём объекты реального мира» — мы научимся объединять данные и функции, которые с ними работают, в одну именованную структуру.