Je me permet de “cornichon objets locaux” si j'utilise une classe dérivée?
La pickle
référence les états qui de l'ensemble des objets qui peuvent être traitées est plutôt limitée. En effet, j'ai une fonction qui retourne un dinamically-classe générée, et je l'ai trouvé je ne peux pas pickle instances de cette classe:
>>> import pickle
>>> def f():
... class A: pass
... return A
...
>>> LocalA = f()
>>> la = LocalA()
>>> with open('testing.pickle', 'wb') as f:
... pickle.dump(la, f, pickle.HIGHEST_PROTOCOL)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: Can't pickle local object 'f.<locals>.A'
De tels objets sont trop compliqués pour pickle
. Ok. Maintenant, ce qui est magique, c'est que, si j'essaie de pickle un objet similaire, mais d'une classe dérivée, il fonctionne!
>>> class DerivedA(LocalA): pass
...
>>> da = DerivedA()
>>> with open('testing.pickle', 'wb') as f:
... pickle.dump(da, f, pickle.HIGHEST_PROTOCOL)
...
>>>
Ce qui se passe ici? Si c'est si facile, pourquoi ne pas pickle
utiliser cette solution de contournement à mettre en œuvre un dump
méthode qui permet de "objets locaux" pour être nettoyée?
OriginalL'auteur fonini | 2016-05-03
Vous devez vous connecter pour publier un commentaire.
Je pense que vous n'avez pas lu la référence que vous citez soigneusement. La référence également stipule clairement que seuls les objets suivants sont pickleable:
Votre exemple
ne permet pas de définir une classe à haut niveau d'un module, il définit une classe au sein de l' portée de
f()
.pickle
fonctionne sur mondiale classes, pas de classes locales. Automatiquement à l'échec de la pickleable test.DerivedA
est une classe globale, donc tout va bien.Comme pour pourquoi seul le haut-niveau (mondial) des classes et des fonctions ne peuvent pas être traitées, la référence répond à la question ainsi que le gras de la mine):
Donc là vous l'avez.
pickle
seulement serialises objets par référence de nom, pas par les premières instructions contenues dans l'objet. C'est parce quepickle's
travail est de serialise objet de la hiérarchie, et rien d'autre.Par ailleurs, si je unpickle dans un environnement dans lequel il ya une autre catégorie, mais avec le même nom, je vais obtenir quelques frankstein monstre objet du présent sans rapport avec la classe, mais avec les attributs de la vieille classe? Je pense que ça se résume à: marinés objets ne sont pas aussi autonomes que je pensais qu'ils étaient.
Aussi à partir de la référence: "... lorsque les instances de classe sont décapés, leur code et les données ne sont pas marinés avec eux. Seules les données d'instance sont décapés. "Donc, oui, qui sonne comme le droit de comportement. 🙂
Je suis entièrement d'enjamba.
OriginalL'auteur Akshat Mahajan
Je suis en désaccord, vous pouvez cornichon à la fois. Vous avez juste besoin d'utiliser un meilleur sérialiseur, comme
dill
.dill
(par défaut) cornichons classes par la sauvegarde de la définition de la classe au lieu de décapage par référence, de sorte qu'il ne s'agit pas de votre premier cas. Vous pouvez même utiliserdill
d'obtenir le code source, si vous le souhaitez.dill
n'est pas plus rapide, et aussi pas de mieux en termes de taille de l'objet stocké. En effet, c'est pire quepickle
dans ces deux domaines. Il est de loin meilleur, en termes de capacité de sérialiser les différents types d'objets, et c'est ce que je voulais dire.OriginalL'auteur Mike McKerns
DerivedA
instances sont pickleable parce queDerivedA
est disponible via une variable globale correspondant à son nom pleinement qualifié, qui est de savoir commentpickle
regarde pour les classes lors de la unpickling.Le problème avec le fait d'essayer de faire quelque chose comme ça avec les classes locales est qu'il n'y a rien d'identification qui
A
classe une instance correspond à. Si vous exécutezf
deux fois, vous obtenez deuxA
classes, et il n'y a aucun moyen de dire ce qui doit être la classe de unpickledA
des instances à partir d'une autre exécution du programme. Si vous ne courez pasf
à tous, vous obtenez pasA
classes, et puis que diable faites-vous à propos du type de unpickled instances?OriginalL'auteur user2357112
Vous ne pouvez pickle des instances de classes définies au module de haut niveau.
Cependant, vous pouvez pickle instances définies localement des classes si vous les promouvoir à plus haut niveau.
Vous devez définir la __ qualname__ de l'attribut de classe de la classe locale. Ensuite, vous devez attribuer la classe à un haut-niveau de la variable du même nom.
OriginalL'auteur haael