Rozdział 13 · Automatyzacja z funkcjami

Mini-projekt — Turtle Function Studio

Kształty z rozdziałów 6 i 10 stają się prawdziwą wielokrotnego użytku funkcją z wyraźnymi parametrami — i zamykamy cały rozdział funkcji.

Zastosowanie
defпараметрыциклыTurtle
Poziom
★★★★ challenge
Rezultat
Turtle graficznych

Co tworzymy

Projekt końcowy rozdziału: przekształcimy powtarzający się kod rysowania figur z rozdziałów 6 i 10 w prawdziwą, wielokrotnego użytku funkcję z parametrami.

Przepływ danych funkcji

WYZWANIEdraw_polygon(artist,6, 80)PARAMETRYartist, sides=6,length=80OBLICZENIAangle = 360 / sidesCYKLsides razyPRAWDZIWE WNIOSKIsześciokąt
Jeden wywołanie — parametry rozwijają się w obliczenie, pętlę i wynikowy rysunek
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()
Rezultat
Regularny sześciokąt rysowany przez funkcję draw_polygon
draw_polygon(artist, 6, 80) — prawidłowy sześciokąt

Dlaczego funkcja przyjmuje artist jawnie

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)    # kwadrat
draw_polygon(artist, 3, 100)    # trójkąt, bez powtarzania kodu!
draw_polygon(artist, 8, 60)     # ośmiokąt
Parametr artist jawny nie jest zbędną formalnością
Funkcja mogłaby polegać na zmiennej globalnej artist, jak w rozdziale 10. Ale parametr sprawia, że zależność jest WIDOCZNA (§13.15): od razu widać, że funkcja działa dokładnie z tą żółwikiem, którą jej przekazano — można ją ponownie wykorzystać z inną żółwikiem (na przykład podczas wyścigu Turtle z §12.6, gdzie jest kilka żółwi) bez żadnej zmiany kodu wewnątrz.

Funkcja wewnątrz pętli: to samo zachowanie, nowy parametr na każdym kroku

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()
Rezultat
Wachlarz z sześciu obróconych wielokątów od trójkąta do ośmiokąta, narysowany pętlą wywołującą draw_polygon
Pętla powoduje draw_polygon z nowym sides na każdym kroku — wachlarzem wielokątów
Pętla automatyzuje powtarzanie, funkcja automatyzuje zachowanie
Dokładnie idea §13.1: pętla decyduje ILE RAZY i z jakimi danymi wywołać draw_polygon; sama funkcja decyduje, JAK narysować wielokąt na podstawie tych danych. Żadne z tych dwóch narzędzi nie zastępuje drugiego.
Challenge
Funkcja z pozycją

Dodaj parametry x, y (z domyślnymi wartościami 0, 0) do funkcji, aby móc określić, od czego zacząć rysować kształt.

Praktyka: Turtle Function Studio
Moduł turtle otwiera natywne okno Python – uruchamiane lokalnie w VS Code, PyCharm lub Jupyter
Praktyka kursuje lokalnie
Otwórz praktykę →

Podsumowanie rozdziału

Zestaw narzędzi do projektowania funkcji

Ostatni zestaw narzędzi rozdziału 13
Potrzebujesz ponownie użyć tego samego zestawu akcji?
wyróżnij funkcję
Czy funkcja wymaga wejścia?
parametry
Trzeba zwrócić wynik do przyszłego użytku?
return
Czy liczba kłótni może być nieznana?
*args / **kwargs
Czy niektóre argumenty powinny być opcjonalne?
domyślne ustawienia (niezmienialne!)
Niektóre argumenty powinny być przekazywane tylko po nazwie?
keyword-only, po *
Czy funkcja powinna zachowywać się przewidywalnie i łatwo ją testować?
czysta funkcja, bez efektów ubocznych
Czy trzeba przekazać samą funkcję jako wartość?
funkcja jest obiektem pierwszej klasy
Potrzebna jest malutka zasada dla sorted()/max()?
lambda
Pełna lista kontrolna projektu w §13.18

Czego nauczyliśmy się w tym rozdziale

  • Funkcja to nazwany, wielokrotnego użytku element zachowania: odbiera dane (parametry), pracuje z nimi, zwraca wynik (return).
  • Wywołanie funkcji przekazuje sterowanie do jej ciała i koniecznie wraca do miejsca wywołania — funkcja nie wykonuje się „gdzieś obok”
  • Parametr to nazwa w definicji, argument to wartość w wywołaniu. Przypisanie parametru i mutacja przekazanego obiektu to dwie różne akcje o różnych konsekwencjach na zewnątrz.
  • Domyślna wartość zmienna jest tworzona RAZ przy definiowaniu funkcji — użyj None jako sygnał zamiast [] lub {}.
  • *args oraz **kwargs zbierają zbędne argumenty w krotkę i słownik odpowiednio; to samo */** rozpakowuje kolekcję z powrotem w momencie rozmowy.
  • Funkcja bez return wciąż wraca None nie jest „niczym”
  • Python szuka nazwy zgodnie z zasadą LEGB: Local → Enclosing → Global → Builtins.
  • Funkcje wywołujące funkcje tworzą stos wywołań — a traceback z rozdziału 3 pokazuje ten stos w momencie wystąpienia błędu.
  • Funkcje — obiekty pierwszej klasy: można je zapisać pod inną nazwą, umieścić w kolekcjach, przekazać innym funkcjom (sorted(key=...)).
  • lambda — mała anonimowa funkcja dla jednego wyrażenia, nie więcej „nowoczesna" zamiana def.
  • Refaktoryzacja dużego skryptu do zestawu funkcji sprawia, że główny program jest czytelnym opisem algorytmu, a każda część jest niezależnie testowalna.

co dalej

Nauczyliśmy się grupować ZACHOWANIE w funkcjach. Ale w wielu naszych projektach dane i zachowanie, które z nimi współdziała, naturalnie idą w parze — kontakt z własnym telefonem, uczeń ze swoją oceną, żółw ze swoim kolorem i pozycją. W następnym rozdziale — „Tworzenie rzeczywistych obiektów” – nauczymy się, jak łączyć dane i funkcje, które współtworzą jedną nazwaną strukturę.