

\usepackage{fontspec}
\usepackage{polyglossia}
\setdefaultlanguage[
  spelling=new
  ,variant=german
]{german}

\usetheme{default}

\usepackage{minted}
\setminted{
  %fontsize=\small,
  style=default
}

\title{Python typing}
\author{Hong-Phuc Bui}
\institute{HTW Saar}

\begin{document}
\begin{frame}[plain]
    \maketitle
\end{frame}


\begin{frame}[plain]
\tableofcontents
\end{frame}

\section{Primitiven Typen}
\begin{frame}[fragile]
\frametitle{Einfache Nutzung}
\begin{minted}{python}
# filename: developer.py
# integer
staff: int = 123_456

# float
developer_quote: float = 0.7

# string
team: str = "DevOp"

developer: int = developer_quote * staff

# Bug!
print(f"Es gibt {developer} Entwickler in Team „{team}“!")
\end{minted}
\pause
\begin{minted}{python}
# → Es gib 86419.2 Entwickler in Team „DevOp“!
\end{minted}
Wir wollen keine ein-fünftel Entwickler!
\end{frame}

\begin{frame}[fragile]
% \frametitle{Bugfix}
Eine Variante ist explizite Konvertierung.

\begin{minted}{python}
# Bugfix:
developer: int = int(developer_quote * staff)

# Bugfixed
print(f"Es gibt etwa {developer} Entwickler in Team „{team}“!")
\end{minted}

\end{frame}


\begin{frame}[fragile]
\frametitle{Konstante}
\begin{minted}{python}
# filename: light-speed.py
from typing import Final

LIGHT_SPEED: Final[int] = 299_792_458  # Exact value [m/s]

LIGHT_SPEED = 299_792.458  # [km/s]
\end{minted}
\pause

Keine Fehlermeldung!
\end{frame}

\subsection{Typen Überprüfen}
\begin{frame}[fragile]
\frametitle{Run Type-check}
{\footnotesize
\begin{minted}{text}
$ python3 -m pip install mypy
$ mypy light-speed.py
light-speed.py:5: error: Cannot assign to final name "LIGHT_SPEED"  [misc]
light-speed.py:5: error: Incompatible types in assignment 
    (expression has type "float", variable has type "int")  [assignment]
Found 2 errors in 1 file (checked 1 source file)
\end{minted}
}

\end{frame}


\section{Zusammengesetzten Typen}
\begin{frame}[fragile]
\frametitle{Zusammengesetzten Typen}
\begin{minted}{python}
# list of prof
prof: list[str] = ["D. Knuth", "R. Sedgwick", "E. Gamma"]

# grade is a tuple of student and his note
grade: tuple[str, float] = ("Tommy", 12.5)

# set of all possible notes
notes: set[str] = {"A", "B", "C", "D", "E"}

# dictionary
german_articles: dict[str, str] = {
    "der": "the", "des": "the", "dem": "the", "den": "the",
    "die": "the",
    "das": "the",
}
\end{minted}
\end{frame}

\subsection{Union}
\begin{frame}[fragile]
\frametitle{Union}
\begin{minted}{python}
from typing import Sequence


measurement: Sequence[int | float] = [12.5, 11, 12.3, 11.6, 11.1, 12]
\end{minted}
\pause

Wozu ist das gut?
\end{frame}


\begin{frame}[fragile]
\frametitle{Funktionsparameter}

\begin{minted}{python}
def avg(values: Sequence[int | float]) -> float:
    return sum(values) / len(values)
\end{minted}
\vspace{5ex}
\pause
\begin{minted}{python}
from typing import Sequence, Callable

avg: Callable[[Sequence[int | float]], float] = \
    lambda values: sum(values) / len(values)
\end{minted}
\end{frame}


\subsection{TypeAlias}
\begin{frame}[fragile]
\frametitle{TypeAlias}
\begin{minted}{python}
from typing import Sequence, Callable, TypeAlias


Scale: TypeAlias = Sequence[int | float]

avg: Callable[[Scale], float] = \
    lambda values: sum(values) / len(values)
    
# noch besser:    
avg: Callable[[Scale], float] = \
    lambda v: sum(v) / len(v) if len(v) > 0 else 0.0
\end{minted}
\end{frame}

\section{Referenz}
\begin{frame}[fragile]
\frametitle{Referenz}
\begin{enumerate}
\item \url{https://mypy.readthedocs.io/}
\item \url{https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html}
\end{enumerate}

\vfill
Weiter lesen: Was ist der Unterschied zwischen Iterable und Sequence?

\end{frame}

\end{document}
 