Singleton

Le problème est d'instancier une classe une seule et unique fois. Il existe plusieurs solutions en Python, mais la plus élégante à mes yeux est celle qui surcharge la méthode __new__() :

class Singleton(object):
   _instance = None

   def __new__(cls):
       if cls._instance is None:
           cls._instance = object.__new__(cls)
       return cls._instance

objet1 = Singleton()
objet2 = Singleton()
print id(objet1) == id(objet2)   # Affiche 'True'

Note: la fonction id() donne l'identifiant unique de chaque objet.

Cet exemple est d'un simplicité déconcertante : seulement 6 lignes de code sont nécessaires dans la classe, et au niveau de l'utilisation (instanciation de la classe) il n'y a rien à faire !

Adaptateur (adapter en anglais)

Mon problème était d'ajouter des attributs à des objets de nature quelconque. L'héritage n'était pas envisageable, car je ne voulais pas avoir à écrire N classes pour N types d'objet différents, bien que cela eût été possible en utilisant le motif de conception « fabrication » (factory en anglais). La clé de la solution est la méthode __getattr__(), méthode appelée lorsqu'on accède à un attribut d'un objet :

class Adaptateur:
    def __init__(self, objet, dico):
        assert hasattr(objet, "valeur")
        self._objet = objet
        self._dico = dico

    def __getattr__(self, nom):
        if nom != "texte":
            return getattr(self._objet, nom)
        else:
            return self._litTexte()

    def _litTexte(self):
        key = self._objet.valeur
        if key in self._dico:
            return self._dico[key]
        else:
            return self._objet.display

adapt = Adaptateur( Nombre(...), {0: "zéro", 1: "un"})
print adapt.valeur   # lit en fait adapt._objet.valeur
print adapt.texte  # appelle adapt._litTexte()

La classe "Adaptateur" va en fait changer le comportement de l'attribut « texte » de l'objet. Si la valeur de l'objet appartient au dictionnaire passé en argument du constructeur, alors c'est la valeur dans ce dictionnaire qui est renvoyée. Sinon, on renvoie simplement l'attribut texte de l'objet. Cet outil accepte donc n'importe quel objet en entrée. La seule condition étant qu'il possède un attribut « valeur » (une assertion s'occupe d'ailleurs de vérifier cette pré-condition).