4 votes

Retour de différents objets lors de l'instanciation

Lorsque j'instancie une classe particulière que j'ai écrite, je lui attribue un nom et plusieurs propriétés en tant qu'arguments de __init__. En fonction du nom passé, mon __init__ tente de trouver un fichier sur le disque qui correspond à ce nom et, au lieu de traiter les autres arguments passés, il lit tous ces éléments à partir du fichier. Et si le fichier n'est pas trouvé, les arguments sont utilisés à la place.

Maintenant je me demande, si je voulais utiliser pickle pour stocker l'objet entier au lieu d'utiliser mes propres routines pour écrire des fichiers, comment pourrais-je accomplir le chargement? Je ne peux pas désérialiser mon objet à l'intérieur de __init__ car l'objet a déjà été créé, n'est-ce pas?

Une idée que j'ai est d'écrire une méthode de classe que j'utiliserais pour l'instanciation à la place, et qui renverrait un objet désérialisé s'il est stocké sur le disque, sinon il créerait un nouvel objet avec les paramètres passés.

Une autre idée est d'utiliser __new__ au lieu d'une méthode de classe qui renverrait un objet, cependant je ne sais pas si c'est l'utilisation prévue de __new__.

Ces idées sont-elles bonnes ou existe-t-il un meilleur moyen d'accomplir ceci?

4voto

larsmans Points 167484

Utilisez une fonction d'usine au lieu de le faire dans __init__. Exemple :

class Foo(object):
    # whatever

def get_foo(path, *args, **kwargs):
    try:
        obj = pickle.load(open(path))
        if not isinstance(obj, Foo):
            raise TypeError, "%s does not contain a Foo" % path
        return obj
    except IOError as e:
        if e[0] == errno.ENOENT:
            return Foo(*args, **kwargs)
        else:
            raise

0voto

Rob Cowie Points 10471

J'aime assez utiliser une classmethod pour ce genre de chose car cela sépare la logique des cas spéciaux de la logique d'initialisation de la classe 'standard'. Par exemple.

class MyClass(object):
    @classmethod
    def load(cls, name, **kargs):
        try:
            state = state_from_file(name) ## votre code de chargement
        except Exception:
            state = kargs
        return cls(name, **state)

    def __init__(self, name, food=None, **kargs):
        self.name = name
        self.food = food

d = MyClass(name='eric', food='spam & eggs')
d = MyClass.load(name='eric', food='spam & eggs')

En ce qui concerne la manière de persister l'état de votre objet... Je ne suis pas vraiment fan d'utiliser pickle; Sans doute cela fonctionne, mais je trouve plus facile de sauvegarder explicitement l'état de votre instance en utilisant un format comme json, yaml, etc. Cela semble 'plus sûr' en termes de compatibilité de la plateforme, de la pérennité, etc. Peu importe. Si vous isolez correctement votre code de persistance, vous pouvez assez facilement le remplacer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X