Python 3.10 : récapitulatif des nouveautés
Pep 604
Tester plusieurs types avec le | :
isinstance(5, int | str)
isinstance(None, int | None)
isinstance(42, None | int)
issubclass(bool, int | float)
Même chose pour les annotations :
def ma_fonction(
        ma_liste: List[int | str],
        param: int | None
    ) -> float | str:
    pass
Messages d’erreur plus parlants
- L’erreur est maintenant affichée à la ligne de début du problème, et non plus lorsque l’interpréteur n’y comprend plus rien, l’exemple le plus marquant étant avec l’oubli d’une parenthèse fermante, ou d’une mauvaise indentation
 - Les messages ont été corrigés de manière à ce qu’ils soient plus clairs, avec des suggestions très utiles qui correspondent souvent à l’erreur
 
Le match/case
Le match/case de Python est similaire à l’instruction switch/case, qui est reconnue comme un “pattern matching structurel” en Python.
Le match/case de Python se compose de trois entités principales :
- Le mot-clé 
match - Une ou plusieurs clauses 
case - Du code pour chaque 
case 
Là où Python se démarque des autres langages, c’est que l’on peut faire un match sur des patterns !
Exemples de match, du plus simple au plus avancé :
Match très simple, avec le “or”
exemple = True
match exemple:
    case (True|False):
        print("C'est un booléen")
    case _ :
        print("Ce n'est pas un booléen")
Récupérer les sous-patterns
def alarm(item):
    match item:
        case [time, action]:
            print(f"{time} ! C'est l'heure de {action}!")
        case [time, *actions]:
            print(f'{time} !')
            for action in actions:
                print(f"C'est l'heure {action}!")
alarm(['Bon après-midi', 'de travailler'])
alarm(['Bonjour', 'du petit déjeuner', 'se laver les dents'])
Nommer les sous-patterns
def alarme(item):
    match item:
        case [('bonjour' | 'bonsoir') as time, action]:
            print(f"{time.title()} ! Il faudrait {action} !")
        case _:
            print('Mot-clé invalide.')
alarme(['bonsoir', 'travailler'])
alarme(['bonjour', 'petit déjeuner', 'se laver les dents'])
Nommer les sous-patterns et filtres conditionnels
def alarme(item):
    match item:
        case ['bonsoir', action] if action not in ['travailler']:
            print(f'Journée finie ! Il faut {action}!')
        case ['bonsoir', _]:
            print('Il faut se reposer !')
        case [time, *action]:
            print(f'{time.title()}! Il faut {" et ".join(action)}.')
        case _:
            print('Mot-clé invalide.')
alarme(['bonsoir', 'travailler'])
alarme(['bonsoir', 'jouer'])
alarme(['bonjour', 'petit déjeuner', 'se laver les dents'])
Match sur des objets
class Move:
    def __init__(self, horizontal=None, vertical=None):
        self.horizontal = horizontal
        self.vertical = vertical
def str_move(move):
    match move:
        case Move(horizontal='est', vertical='nord'):
            print('Dir. nord-est')
        case Move(horizontal='est', vertical='sud'):
            print('Dir. sud-est')
        case Move(horizontal='ouest', vertical='nord'):
            print('Dir. nord-ouest')
        case Move(horizontal='ouest', vertical='sud'):
            print('Dir. sud ouest')
        case Move(horizontal=None):
            print(f'Dir. {move.vertical}')
        case Move(vertical=None):
            print(f'Dir. {move.horizontal}')
        case _:
            print('? Move inconnu ?')
d1 = Move('est', 'sud')
d2 = Move(vertical='nord')
d3 = Move('centre', 'centre')
str_move(d1)
str_move(d2)
str_move(d3)