Question

Indépendamment de savoir si l’utilisation de isinstance est nocif , je suis tombé sur le suite à l'énigme lors de la tentative d'évaluation isinstance après la sérialisation / désérialisation d'un objet via Pickle:

from __future__ import with_statement
import pickle

# Simple class definition
class myclass(object):
    def __init__(self, data):
        self.data = data

# Create an instance of the class
x = myclass(100)

# Pickle the instance to a file
with open("c:\\pickletest.dat", "wb") as f:
    pickle.dump(x, f)

# Replace class with exact same definition
class myclass(object):
    def __init__(self, data):
        self.data = data

# Read an object from the pickled file
with open("c:\\pickletest.dat", "rb") as f:
    x2 = pickle.load(f)

# The class names appear to match
print x.__class__
print x2.__class__

# Uh oh, this fails...(why?)
assert isinstance(x2, x.__class__)

Quelqu'un peut-il nous expliquer pourquoi une telle éventualité échouerait dans cette situation? En d'autres termes, pourquoi Python pense-t-il que ces objets appartiennent à deux classes différentes? Lorsque je supprime la deuxième définition de classe, isinstance fonctionne correctement.

Était-ce utile?

La solution

Voici comment fonctionne le dépickeur (site-packages / pickle.py):

def find_class(self, module, name):
    # Subclasses may override this
    __import__(module)
    mod = sys.modules[module]
    klass = getattr(mod, name)
    return klass

Pour rechercher et instancier une classe.

Donc, bien sûr, si vous remplacez une classe par une classe de nom identique, le klass = getattr (mod, nom) renverra la nouvelle classe et l'instance sera de la nouvelle classe, et alors c’est un échec.

Autres conseils

La réponse évidente, car ce n'est pas la même classe.

C'est une classe similaire, mais pas la même chose.

class myclass(object):
    pass

x = myclass()

class myclass(object):
    pass

y = myclass()


assert id(x.__class__) == id(y.__class__) # Will fail, not the same object

x.__class__.foo = "bar"

assert y.__class__.foo == "bar" # will raise AttributeError

Modifiez votre code pour imprimer le id de x .__ classe __ et de x2 .__ classe __ et vous verrez qu'ils sont différents:

$ python foo4.py
199876736
200015248
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top