Języki skryptowe - Python

Wykład 1

Dane kontaktowe


Program


  • wprowadzenie
  • podstawowe typy danych i operatory
  • wyrażenia warunkowe i pętle
  • funkcje i moduły
  • struktury danych
  • klasy i obiekty
  • operacje wejścia/wyjścia
  • obsługa wyjątków

  • obliczenia numeryczne
  • debugowanie i profilowanie
  • tworzenie graficznego interfejsu użytkownika
  • dekoratory, funkcje lambda, generatory ...

Materiały do wykładów


  • wykłady: https://github.com/TomaszGolan/js-python
  • dokumentacja: https://www.python.org/

  • A. B. Downey, J. Elkner, C. Meyers, “Think Python. How to Think Like a Computer Scientist”: http://www.greenteapress.com/thinkpython/
  • M. Pilgrim, “Dive into Python”: http://www.diveintopython.net/
  • Swaroop CH "A Byte of Python": https://python.swaroopch.com/ (tłumaczenie: http://python.edu.pl/byteofpython/)

Zaliczenie


  • ćwiczenia: listy zadań
  • wykład: egzamin praktyczny

Język kompilowany


  • przykłady: C / C++, Pascal
  • zalety: wydajność, błędy na etapie kompilacji, utrzymanie i rozwijanie kodu
  • wady: czas pisania, kompilacja dużych projektów
from graphviz import Source

Source('digraph "kompilator" { rankdir=LR; node [shape="box", width=2]; \
        "kod źródłowy" -> "kompilator" -> "kod maszynowy" -> "wynik"}')

svg

Język interpretowany


  • przykłady: Python, Perl
  • zalety: prosty, szybki i przyjemny
  • wady: wydajność, debugowanie (brak kompilacji)
Source('digraph "interpreter" { rankdir=LR; node [shape="box", width=2]; \
        "kod źródłowy" -> "interpreter" -> "wynik"}')

svg

Python


Python is powerful... and fast; plays well with others; runs everywhere; is friendly & easy to learn; is Open.


  • otwarte oprogramowanie (open source)
  • przenośny
    • Linux, Mac OS - prawdopodobnie już jest
    • Windows - instalator ze strony https://www.python.org
    • Anaconda - https://www.continuum.io/
  • zwięzły i elegancki (prawie jak pseudokod)
  • automatyczne zarządzanie pamięcią (garbage collection)
  • bogata bilbioteka standardowa i niezliczona ilość bibliotek zewnętrznych
  • struktury wysokiego poziomu
import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Hello World!


# Python
print("Hello World!")

// C++
#include <iostream>

int main()
{
    std::cout << "Hello World!";
}

// Java
public class Hello {
    public static void main(String []args) {
        System.out.println("Hello World!");
    }
}

Zastosowanie


  • internet: Yahoo, Google, ...
  • gry: Battlefield 2, Civilization 4, ...
  • grafika: Walt Disney, Blender 3D, ...
  • finanse: Altis Investment Management, Bellco Credit Union, ...
  • nauka: NASA, Los Alamos National Laboratory, ...
  • interfejs programistyczny aplikacji (Application Programming Interface = API): tensorflow (Google's machine learning), Amazon, Facebook, Youtube, ...

Python 2 vs Python 3


  • Short version: Python 2.x is legacy, Python 3.x is the present and future of the language (https://wiki.python.org/moin/Python2orPython3)
  • Python 3 jest gotowy, jednak nie wszystkie zewnętrzne biblioteki są już z nim kompatybilne

Python 2 vs Python 3


  • Niektóre zmiany są kosmetyczne
# Python 2

print "Hello World!"

# Python 3

print("Hello World!")

Python 2 vs Python 3


  • Niektóre niebezpieczne
# Python 2

3 / 2.0 # = 1.5
3 / 2   # = 1

# Python 3

3 / 2.0 # = 1.5
3 / 2   # = 1.5
3 // 2  # = 1

Python 2 vs Python 3


  • A niektóre gruntowne: iteratory
  • Niektóre elementy Pythona 3 można zaimportować w Pythonie 2
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 3 / 2
1
>>> from __future__ import division
>>> 3 / 2
1.5
>>> 
  • Więcej informacji: https://wiki.python.org/moin/Python2orPython3

  • Na wykładzie omawiany będzie Python 3

Tryb interaktywny


$ python
Python 3.5.2 |Anaconda custom (64-bit)| (default, Jul  2 2016, 17:53:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> oceny_uwr = {2.0: "niedostateczny", 3.0: "dostateczny",
...              3.5: "dostateczny plus", 4.0: "dobry",
...              4.5: "dobry plus", 5.0: "bardzo dobry"}
>>> for ocena in sorted(oceny_uwr, reverse=True):
...     print(ocena, oceny_uwr[ocena])
... 
5.0 bardzo dobry
4.5 dobry plus
4.0 dobry
3.5 dostateczny plus
3.0 dostateczny
2.0 niedostateczny
>>> 

Tryb skryptowy


$ cat skala_ocen.py 
#!/usr/bin/env python

oceny_uwr = {2.0: "niedostateczny", 3.0: "dostateczny",
             3.5: "dostateczny plus", 4.0: "dobry",
             4.5: "dobry plus", 5.0: "bardzo dobry"}

for ocena in sorted(oceny_uwr, reverse=True):
    print(ocena, oceny_uwr[ocena])

$ python skala_ocen.py 
5.0 bardzo dobry
4.5 dobry plus
4.0 dobry
3.5 dostateczny plus
3.0 dostateczny
2.0 niedostateczny

Tryb skryptowy


$ ./skala_ocen.py
bash: ./skala_ocen.py: Permission denied

$ chmod +x skala_ocen.py 

$ ./skala_ocen.py 
5.0 bardzo dobry
4.5 dobry plus
4.0 dobry
3.5 dostateczny plus
3.0 dostateczny
2.0 niedostateczny

Jupyter


oceny_uwr = {2.0: "niedostateczny", 3.0: "dostateczny",
             3.5: "dostateczny plus", 4.0: "dobry",
             4.5: "dobry plus", 5.0: "bardzo dobry"}

for ocena in sorted(oceny_uwr, reverse=True):
    print(ocena, oceny_uwr[ocena])
5.0 bardzo dobry
4.5 dobry plus
4.0 dobry
3.5 dostateczny plus
3.0 dostateczny
2.0 niedostateczny

Czytelność kodu


  • przejrzysty kod
  • zrozumiałe nazwy zmiennych
  • komentarzy nigdy za wiele
  • dzielenie linii nie boli
  • konsekwencja w konwencji
  • najlepiej trzymać się standardu PEP 8: https://www.python.org/dev/peps/pep-0008/
  • ale bez przesady - przede wszystkim kod ma być czytelny

Czytelność kodu


import random

# skala ocen obowiązująca na Uniwersytecie Wrocławskim
oceny_uwr = {2.0: "niedostateczny", 3.0: "dostateczny",
             3.5: "dostateczny plus", 4.0: "dobry",
             4.5: "dobry plus", 5.0: "bardzo dobry"}

# lista studentów uczęszczających na zajęcia z Pythona
lista_studentow = ["Kasia", "Basia", "Józek", "Marek"]

# przez lenistwo prowadzącego oceny wystawiane losowo
for student in lista_studentow:
    # losowa ocena
    ocena = random.choice(list(oceny_uwr))
    # przypisanie oceny
    print(student, " -> ", oceny_uwr[ocena])
Kasia  ->  dobry plus
Basia  ->  dobry plus
Józek  ->  dostateczny plus
Marek  ->  niedostateczny

Czytelność kodu


import random
o = {2.0: "niedostateczny", 3.0: "dostateczny", 3.5: "dostateczny plus", 4.0: "dobry", 4.5: "dobry plus", 5.0: "bardzo dobry"}
s = ["Kasia", \
     "Basia", "Józek",
     "Marek"]
for i in range(len(s)): x = random.randint(2, len(o) - 1); print(s[i], " -> ", o[x])
Kasia  ->  dostateczny
Basia  ->  niedostateczny
Józek  ->  dostateczny
Marek  ->  bardzo dobry

Podstawowe typy danych


  • typ całkowity (int)
  • typ zmiennoprzecinkowy (float)
  • typ zespolony (complex)
  • typ tekstowy (str)
  • zmienne są typowane dynamicznie
x = 1   # [zmienna] [operator przypisania] [wartość]
y = 1.0
z = 1j

# drukuj typy zmiennych x, y i z (oddzielone przecinkiem)
print(type(x), type(y), type(z), sep=", ")
<class 'int'>, <class 'float'>, <class 'complex'>
x = y # przypisz zmiennej x wartość zmiennej y

type(x) # a czemu nie <class 'float'>?
float

Operacje na liczbach


2 + 2 # suma dwóch liczb całkowitych -> liczba całkowita
4
2 + 2.0 # wynikiem tej sumy jest liczba zmiennoprzecinkowa
4.0
5 - 2
3
-5 * 2 
-10
5 / 2 # w Pythonie 3 dzielenie zawsze zwraca liczbę zmiennoprzecinkową
2.5
6 / 2 # nawet jeśli jest "całkowita"
3.0
5 // 2 # chyba że użyjemy //
2

Operacje na liczbach


5 % 2 # reszta z dzielenia (operator modulo)
1
int(2.5) # jawne rzutowanie na int
2
float(1) # jawne rzutowanie na float
1.0
complex(1,1) # liczby zespolone
(1+1j)
1+1j # można wprowadzać na dwa sposoby
(1+1j)
(1+2j).real # część rzeczywista
1.0
(1+2j).imag # część urojona
2.0

Operacje na liczbach


abs(-10) # moduł
10
abs(-2.5)
2.5
abs(1+1j) # moduł liczby zespolonej
1.4142135623730951
int(1+1j) # rzutowania bez sensu zwrócą błąd
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-26-dd7895e870c6> in <module>()
----> 1 int(1+1j) # rzutowania bez sensu zwrócą błąd


TypeError: can't convert complex to int
(1+1j).conjugate() # sprzężenie liczby zespolonej
(1-1j)

Operacje na liczbach


divmod(10, 3) # para (10 // 3 i 10 % 3)
(3, 1)
divmod(10, 3+1j) # no bo jak...
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-29-0f920bac9923> in <module>()
----> 1 divmod(10, 3+1j) # no bo jak...


TypeError: can't take floor or mod of complex number.
pow(2, 3) # pow(a, b) = a^b
8
pow(2, 3.0) # zwróć uwagę na typy
8.0
2 ** 3 # inna wersja a^b
8
1j ** 2 # dla zespolonych też działa
(-1+0j)

Moduł math


import math # import [moduł]

dir (math) # lista dostępnych funkcji
['__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'acos',
 'acosh',
 'asin',
 'asinh',
 'atan',
 'atan2',
 'atanh',
 'ceil',
 'copysign',
 'cos',
 'cosh',
 'degrees',
 'e',
 'erf',
 'erfc',
 'exp',
 'expm1',
 'fabs',
 'factorial',
 'floor',
 'fmod',
 'frexp',
 'fsum',
 'gamma',
 'gcd',
 'hypot',
 'inf',
 'isclose',
 'isfinite',
 'isinf',
 'isnan',
 'ldexp',
 'lgamma',
 'log',
 'log10',
 'log1p',
 'log2',
 'modf',
 'nan',
 'pi',
 'pow',
 'radians',
 'sin',
 'sinh',
 'sqrt',
 'tan',
 'tanh',
 'trunc']

Moduł math


help(math.floor) # dokumentacja funkcji floor z math
Help on built-in function floor in module math:

floor(...)
    floor(x)

    Return the floor of x as an Integral.
    This is the largest integer <= x.
help(math.ceil) # zwróć uwagę na: moduł.funkcja
Help on built-in function ceil in module math:

ceil(...)
    ceil(x)

    Return the ceiling of x as an Integral.
    This is the smallest integer >= x.

Moduł math


int(2.8) # rzutowanie float na int "ucina wszystko po kropce"
2
math.floor(2.8) # tak jak funkcja math.floor
2
math.ceil(2.8) # funkcja math.ceil zaokrągla w górę
3
math.ceil(2.1) # zawsze w górę (patrz definicja)
3

Moduł math


import cmath # biblioteka standardowa dla liczb zespolonych

dir(cmath) # porównaj z dir(math), jasne czemu moduł.funkcja?
['__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'acos',
 'acosh',
 'asin',
 'asinh',
 'atan',
 'atanh',
 'cos',
 'cosh',
 'e',
 'exp',
 'isclose',
 'isfinite',
 'isinf',
 'isnan',
 'log',
 'log10',
 'phase',
 'pi',
 'polar',
 'rect',
 'sin',
 'sinh',
 'sqrt',
 'tan',
 'tanh']

Moduł math


cmath.sqrt(-1) # cmath potrafi
1j
math.sqrt(-1) # ale math już nie
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-43-9baf3c39fc4a> in <module>()
----> 1 math.sqrt(-1) # ale math już nie


ValueError: math domain error

Typ tekstowy


  • Python 3 używa domyślnie kodowania unicode dla typu str
  • Dzięki czemu mamy polskie znaki od ręki
Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul  2 2016, 17:53:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> s = "zażółć gęślą jaźń"
>>> s
'zażółć gęślą jaźń'
>>> 

Typ tekstowy bez unicode


Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> s = "zażółć gęślą jaźń"
>>> s
'za\xc5\xbc\xc3\xb3\xc5\x82\xc4\x87 g\xc4\x99\xc5\x9bl\xc4\x85 ja\xc5\xba\xc5\x84'
>>> 

Typ tekstowy


  • Literał łańcuchowy można wprowadzić przez:
    • pojedynczy cudzysłów py s = 'zażółć gęślą jaźń'
    • podwójny cudzysłów py s = "zażółć gęślą jaźń"
    • potrójny cudzysłów py s = '''zażółć gęślą jaźń''' s = """zażółć gęślą jaźń"""

Znak ucieczki


  • zmienia interpretację znaku
  • w Pythonie (i prawie zawsze) jest to "\"
print("Ala powiedziała: "Mam kota." ...") # cudzysłów kończy literał
  File "<ipython-input-44-2bf66ab2182a>", line 1
    print("Ala powiedziała: "Mam kota." ...") # cudzysłów kończy literał
                               ^
SyntaxError: invalid syntax
print("Ala powiedziała: \"Mam kota.\" ...") # chyba że "uciekniemy"
Ala powiedziała: "Mam kota." ...
print('Ala powiedziała: "Mam kota." ...') # kombinacja ' i "
Ala powiedziała: "Mam kota." ...
print("Ala powiedziała: 'Mam kota.' ...") # działa w obie strony
Ala powiedziała: 'Mam kota.' ...

Wybrane sekewncje specjalne


  • \n - nowa linia
  • \t - tabulacja
  • \r - powrót kursora
  • \v - pionowa tabulacja
print("\\n wstawia nową linię.\nNowa linia.") # zwróć uwagę na \\n
\n wstawia nową linię.
Nowa linia.
print("\tTabulacja też się przydaje.") # brak spacji po \t
    Tabulacja też się przydaje.

Carriage return


(Jupyter nie rozumie \r)

# nowa forma importowania: from [moduł] import [funkcja]
from time import sleep
# alternatywa: import time

# drukujemy liczby od 0 do 100
for i in range(100):
    print(i, end="%\r") # kończąc każdą linię % i carriage return
    sleep(1) # i czekamy sekundę na następną liczbę
    # alternatywa: time.sleep(1)

Długie łancuchy


tekst = "Lorem Ipsum jest tekstem stosowanym jako przykładowy wypełniacz w przemyśle poligraficznym. Został po raz pierwszy użyty w XV w. przez nieznanego drukarza do wypełnienia tekstem próbnej książki. Pięć wieków później zaczął być używany przemyśle elektronicznym, pozostając praktycznie niezmienionym. Spopularyzował się w latach 60. XX w. wraz z publikacją arkuszy Letrasetu, zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do realizacji druków na komputerach osobistych, jak Aldus PageMaker"

print(tekst)
Lorem Ipsum jest tekstem stosowanym jako przykładowy wypełniacz w przemyśle poligraficznym. Został po raz pierwszy użyty w XV w. przez nieznanego drukarza do wypełnienia tekstem próbnej książki. Pięć wieków później zaczął być używany przemyśle elektronicznym, pozostając praktycznie niezmienionym. Spopularyzował się w latach 60. XX w. wraz z publikacją arkuszy Letrasetu, zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do realizacji druków na komputerach osobistych, jak Aldus PageMaker

Długie łancuchy


tekst = "Lorem Ipsum jest tekstem stosowanym jako przykładowy \
        wypełniacz w przemyśle poligraficznym. Został po raz \
        pierwszy użyty w XV w. przez nieznanego drukarza do \
        wypełnienia tekstem próbnej książki. Pięć wieków później \
        zaczął być używany przemyśle elektronicznym, \
        pozostając praktycznie niezmienionym. Spopularyzował się \
        w latach 60. XX w. wraz z publikacją arkuszy Letrasetu, \
        zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym \
        różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do \
        realizacji druków na komputerach osobistych, jak Aldus PageMaker"

print(tekst)
Lorem Ipsum jest tekstem stosowanym jako przykładowy         wypełniacz w przemyśle poligraficznym. Został po raz         pierwszy użyty w XV w. przez nieznanego drukarza do         wypełnienia tekstem próbnej książki. Pięć wieków później         zaczął być używany przemyśle elektronicznym,         pozostając praktycznie niezmienionym. Spopularyzował się         w latach 60. XX w. wraz z publikacją arkuszy Letrasetu,         zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym         różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do         realizacji druków na komputerach osobistych, jak Aldus PageMaker

Długie łancuchy


tekst = "Lorem Ipsum jest tekstem stosowanym jako przykładowy " \
        "wypełniacz w przemyśle poligraficznym. Został po raz " \
        "pierwszy użyty w XV w. przez nieznanego drukarza do " \
        "wypełnienia tekstem próbnej książki. Pięć wieków później " \
        "zaczął być używany przemyśle elektronicznym, " \
        "pozostając praktycznie niezmienionym. Spopularyzował się " \
        "w latach 60. XX w. wraz z publikacją arkuszy Letrasetu, " \
        "zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym " \
        "różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do " \
        "realizacji druków na komputerach osobistych, jak Aldus PageMaker "

print(tekst) # "slowo" "slowo" = "slowo" + "slowo"
Lorem Ipsum jest tekstem stosowanym jako przykładowy wypełniacz w przemyśle poligraficznym. Został po raz pierwszy użyty w XV w. przez nieznanego drukarza do wypełnienia tekstem próbnej książki. Pięć wieków później zaczął być używany przemyśle elektronicznym, pozostając praktycznie niezmienionym. Spopularyzował się w latach 60. XX w. wraz z publikacją arkuszy Letrasetu, zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do realizacji druków na komputerach osobistych, jak Aldus PageMaker

Długie łancuchy


tekst = "Lorem Ipsum jest tekstem stosowanym jako przykładowy\n" \
        "wypełniacz w przemyśle poligraficznym. Został po raz\n" \
        "pierwszy użyty w XV w. przez nieznanego drukarza do\n" \
        "wypełnienia tekstem próbnej książki. Pięć wieków później\n" \
        "zaczął być używany przemyśle elektronicznym,\n" \
        "pozostając praktycznie niezmienionym. Spopularyzował się\n" \
        "w latach 60. XX w. wraz z publikacją arkuszy Letrasetu,\n" \
        "zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym\n" \
        "różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do\n" \
        "realizacji druków na komputerach osobistych, jak Aldus PageMaker\n"

print(tekst)
Lorem Ipsum jest tekstem stosowanym jako przykładowy
wypełniacz w przemyśle poligraficznym. Został po raz
pierwszy użyty w XV w. przez nieznanego drukarza do
wypełnienia tekstem próbnej książki. Pięć wieków później
zaczął być używany przemyśle elektronicznym,
pozostając praktycznie niezmienionym. Spopularyzował się
w latach 60. XX w. wraz z publikacją arkuszy Letrasetu,
zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym
różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do
realizacji druków na komputerach osobistych, jak Aldus PageMaker

Długie łancuchy


tekst = """Lorem Ipsum jest tekstem stosowanym jako przykładowy
wypełniacz w przemyśle poligraficznym. Został po raz
pierwszy użyty w XV w. przez nieznanego drukarza do
wypełnienia tekstem próbnej książki. Pięć wieków później
zaczął być używany przemyśle elektronicznym,
pozostając praktycznie niezmienionym. Spopularyzował się
w latach 60. XX w. wraz z publikacją arkuszy Letrasetu,
zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym
różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do
realizacji druków na komputerach osobistych, jak Aldus PageMaker
"""

print(tekst)
Lorem Ipsum jest tekstem stosowanym jako przykładowy
wypełniacz w przemyśle poligraficznym. Został po raz
pierwszy użyty w XV w. przez nieznanego drukarza do
wypełnienia tekstem próbnej książki. Pięć wieków później
zaczął być używany przemyśle elektronicznym,
pozostając praktycznie niezmienionym. Spopularyzował się
w latach 60. XX w. wraz z publikacją arkuszy Letrasetu,
zawierających fragmenty Lorem Ipsum, a ostatnio z zawierającym
różne wersje Lorem Ipsum oprogramowaniem przeznaczonym do
realizacji druków na komputerach osobistych, jak Aldus PageMaker

Przykłady prostych programów

# źródło: http://jakevdp.github.io/blog/2013/05/28/a-simple-animation-the-magic-triangle/

from JSAnimation.IPython_display import display_animation
from matplotlib import animation
# importowanie jeszcze inaczej: import [moduł].[funkcja] as [moja nazwa]
import matplotlib.pyplot as plt
import numpy as np

# Set up the axes, making sure the axis ratio is equal
fig = plt.figure(figsize=(6.5, 2.5))
ax = fig.add_axes([0, 0, 1, 1], xlim=(-0.02, 13.02), ylim=(-0.02, 5.02),
                  xticks=range(14), yticks=range(6), aspect='equal', frameon=False)
ax.grid(True)

# Define the shapes of the polygons
P1 = np.array([[0, 0], [5, 0], [5, 2], [0, 0]])
P2 = np.array([[0, 0], [8, 0], [8, 3], [0, 0]])
P3 = np.array([[0, 0], [5, 0], [5, 1], [3, 1], [3, 2], [0, 2], [0, 0]])
P4 = np.array([[0, 1], [3, 1], [3, 0], [5, 0], [5, 2], [0, 2], [0, 1]])

# Draw the empty polygons for the animation
patches = [ax.add_patch(plt.Polygon(P1, fc='g', ec='k', alpha=0.5)),
           ax.add_patch(plt.Polygon(P2, fc='b', ec='k', alpha=0.5)),
           ax.add_patch(plt.Polygon(P3, fc='y', ec='k', alpha=0.5)),
           ax.add_patch(plt.Polygon(P4, fc='r', ec='k', alpha=0.5))]
# This function moves the polygons as a function of the frame i
Nframes = 30
def animate(nframe):
    f = nframe / (Nframes - 1.0)
    patches[0].set_xy(P1 + (8 - 8 * f, 3 - 3 * f + 0.5 * np.sin(f * np.pi)))
    patches[1].set_xy(P2 + (5 * f, 2 * f - 0.5 * np.sin(f * np.pi)))
    patches[2].set_xy(P3 + (8 - 3 * f, 0))
    patches[3].set_xy(P4 + (8, 1 - f))
    return patches

anim = animation.FuncAnimation(fig, animate, frames=Nframes, interval=50)
display_animation(anim, default_mode='once')


Once Loop Reflect
import turtle # kto zna AC Logo?

pen = turtle.Turtle() # o tym na kolejnych wykładach

n_steps = 90 # w ilu krokach robimy 360 stopni

for i in range(n_steps):

    pen.forward(100) # rysuj 100 do przodu
    pen.right(45)    # obróć się w prawo o 45 stopni
    pen.forward(50)  # rysuj 50 do przodu
    pen.left(90)     # obróć się w lewo o 90 stopni
    pen.forward(100) # rysuj do przodu o 100
    pen.right(45)    # obróź się w prawo o 45 stopni

    pen.penup() # podnieś długopis (nie rysuj przy przemieszczeniu)
    pen.setposition(0, 0) # wróć na środek
    pen.pendown() # rysujemy dalej

    pen.right(360/n_steps) # obróć się w prawo o n_stepną część 360
# css prezentacji

from IPython.display import display, HTML

s = """

<style>

.container {
    width: 80% !important;
}

</style>

"""

display(HTML(s))