Vue d'ensemble

Python 3.1, publié le 27 juin 2009, est la première version d'amélioration de la branche 3.x. Alors que Python 3.0 avait brisé la compatibilité pour nettoyer le langage, Python 3.1 se concentre sur les performances et la stabilité.

C'est une version relativement modeste en termes de nouvelles fonctionnalités, mais elle apporte des ajouts très attendus comme OrderedDict et la méthode int.bit_length(). Le module d'entrées/sorties est également significativement amélioré en performances.

Nouveautés majeures

OrderedDict

Le module collections s'enrichit d'un OrderedDict, un dictionnaire qui conserve l'ordre d'insertion des clés. C'est un outil précieux pour le traitement de fichiers de configuration, la sérialisation JSON avec un ordre prévisible, ou encore la création de caches simples de type LRU.

python
from collections import OrderedDict

# Configuration avec un ordre garanti
config = OrderedDict()
config["hote"] = "localhost"
config["port"] = 5432
config["base"] = "ma_base"
config["utilisateur"] = "admin"

# L'ordre est toujours respecté
for cle, valeur in config.items():
    print(f"{cle} = {valeur}")
# hote = localhost
# port = 5432
# base = ma_base
# utilisateur = admin

# Conservation de l'ordre lors d'un aller-retour JSON
import json

donnees_json = '{"nom": "Martin", "age": 35, "ville": "Lyon"}'
resultat = json.loads(donnees_json, object_pairs_hook=OrderedDict)
print(list(resultat.keys()))  # ['nom', 'age', 'ville']

# Déplacement d'un élément en fin de dictionnaire
config.move_to_end("hote")
print(list(config.keys()))  # ['port', 'base', 'utilisateur', 'hote']

int.bit_length()

La méthode int.bit_length() renvoie le nombre de bits nécessaires pour représenter un entier en binaire, sans compter le signe ni les zéros de tête. C'est utile pour déterminer la taille minimale de stockage ou pour des algorithmes de manipulation de bits.

python
# Nombre de bits nécessaires pour représenter un entier
print((0).bit_length())    # 0
print((1).bit_length())    # 1
print((7).bit_length())    # 3  (binaire : 111)
print((255).bit_length())  # 8  (binaire : 11111111)
print((256).bit_length())  # 9  (binaire : 100000000)

# Application pratique : déterminer le type de stockage minimal
def type_stockage_minimal(valeur):
    """Détermine le plus petit type entier pour stocker une valeur."""
    bits = valeur.bit_length()
    if bits <= 8:
        return "uint8"
    elif bits <= 16:
        return "uint16"
    elif bits <= 32:
        return "uint32"
    else:
        return "uint64"

valeurs = [42, 300, 70000, 5000000000]
for v in valeurs:
    print(f"{v:>12} -> {v.bit_length():>2} bits -> {type_stockage_minimal(v)}")
# 42 ->  6 bits -> uint8
# 300 ->  9 bits -> uint16
# 70000 -> 17 bits -> uint32
# 5000000000 -> 33 bits -> uint64

Amélioration du module io

Le module io, introduit en Python 3.0, reçoit d'importantes améliorations de performances dans Python 3.1. Les opérations de lecture et d'écriture de fichiers sont nettement plus rapides, ce qui était un reproche fréquent fait à Python 3.0.

python
# Écriture et lecture en mode texte (str)
with open("exemple.txt", "w", encoding="utf-8") as f:
    f.write("Première ligne\n")
    f.write("Éléments accentués\n")

with open("exemple.txt", "r", encoding="utf-8") as f:
    contenu = f.read()
    print(type(contenu))  # <class 'str'>

# Écriture et lecture en mode binaire (bytes)
donnees = bytes(range(256))
with open("donnees.bin", "wb") as f:
    f.write(donnees)

with open("donnees.bin", "rb") as f:
    contenu_binaire = f.read()
    print(type(contenu_binaire))  # <class 'bytes'>
    print(len(contenu_binaire))   # 256

# Le module io permet aussi de travailler en mémoire
import io

tampon = io.StringIO()
tampon.write("données temporaires\n")
tampon.write("en mémoire\n")
print(tampon.getvalue())
# données temporaires
# en mémoire

Améliorations mineures

  • Les nombres flottants sont désormais affichés avec la représentation la plus courte qui permet de les reconstruire exactement (par exemple 1.1 au lieu de 1.1000000000000001).
  • Le module unittest gagne la méthode assertAlmostEqual et d'autres assertions utiles.
  • Le module json accepte le paramètre object_pairs_hook pour contrôler le type de dictionnaire utilisé lors du décodage.
  • L'importation des modules est légèrement plus rapide.
  • Les fichiers .pyc peuvent être exécutés directement si le fichier .py correspondant n'existe pas.

Dépréciations et suppressions

Python 3.1 ne supprime pas de fonctionnalités majeures, le gros du nettoyage ayant été fait dans Python 3.0. Quelques points notables :

  • Le module compiler est définitivement supprimé.
  • Plusieurs méthodes obsolètes du module unittest sont marquées comme dépréciées (comme assertEquals au profit de assertEqual).
  • Les méthodes contextlib.nested sont dépréciées au profit de la syntaxe with multiple.

Sources