from IPython.core.display import HTML

HTML(open("custom.html", "r").read())
Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Copyright (C) 2014-2023 Scientific IT Services of ETH Zurich,
Contributing Authors: Uwe Schmitt, Mikolaj Rybniski

Typehints¶

Although Python is dynamically typed, one can add type information to variables and functions since Python 3.5.

Such type annotations DONT CHECK FOR TYPES. They can be used for documenting code and can be accessed by exteranl tools like mypy to check potential type conflicts.

There are also external libraries which perform the type checks during runtime: E.g. https://github.com/agronholm/typeguard

PyCharm also offers type checking, see this tutorial and the PyCharm Documentation

Values are annoatated with a :, except return values we use ->:

def add(a: int, b:int) -> int:
    c : int = a + b
    return c

In case you are curious, the annotations are stored in the __annotations__ attribute of the function:

print(add_integers.__annotations__)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 print(add_integers.__annotations__)

NameError: name 'add_integers' is not defined

As one can see the type checks are not performed:

add_integers("a", "b")
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 add_integers("a", "b")

NameError: name 'add_integers' is not defined

The typing from the standard library allows declaration of more complex types. For example this does not work:

def a(x: list[int]) -> int:
    pass

Instead this works:

import typing

def add_many(values: typing.List[float]) -> float:
    return sum(values)

There is also a more abstract type declaration from typing which is more general:

def add_many(values: typing.Sequence[float]) -> float:
    return sum(values)

Another example is types.Union which can be read as "or":

Number = typing.Union[bool, int, float]

def add_numbers(a: Number, b: Number) -> Number:
    return a + b

data classes¶

from dataclasses import dataclass

@dataclass
class Account:
    name: str
    money: float
    
    def has_debts(self) -> bool:
        return self.money < 0
me = Account("Uwe", 1_000_000)   # I wish
print(me)
print(me.has_debts())
Account(name='Uwe', money=1000000)
False
def go_to_cassino(person):
    person.money -= 500_000
    
go_to_cassino(me)
go_to_cassino(me)
go_to_cassino(me)

print(me.has_debts())
True