11 votes

Quand est-ce que type(instance) n'est pas instance.__class__ ?

Python dispose de la fonction intégrée type et chaque instance possède également un __class__ attribut. Je croyais généralement qu'ils renvoyaient la même chose. Même la documentation des deux semble similaire :

instance.__class__

La classe à laquelle appartient une instance de classe.

y

type(object)

Avec un argument, renvoie le type d'un objet.

Toutefois, en abc.ABCMeta.__instancecheck__ il y a une vérification si elles sont identiques (légèrement raccourcies) :

subclass = instance.__class__
subtype = type(instance)
if subtype is subclass:

Quand cela ne sera-t-il plus le cas ? Quand est-ce que type(instance) pas la même chose que instance.__class__ ?

4voto

Maggyero Points 292

type(instance) y instance.__class__ peut être différente, même avec classes de type nouveau comme l'a mentionné Guido dans PEP 3119 :

En outre, isinstance(x, B) est équivalent à issubclass(x.__class__, B) or issubclass(type(x), B) . (Il est possible type(x) y x.__class__ ne sont pas le même objet, par exemple lorsque x est un objet proxy).

Par exemple :

class A:
    pass

class B:
    __class__ = A

b = B()
print(type(b))      # prints <class '__main__.B'>
print(b.__class__)  # prints <class '__main__.A'>

1voto

ppasler Points 2345

C'est le cas des objets de type ancien (qui n'héritent de rien). Ces objets n'ont pas la fonction __class__ propriété. Je pense qu'ils procèdent ainsi pour éviter les erreurs. Exemple pour Python 2.7 :

class A:
    pass

class B(object):
    pass

a = A()
b = B()

print(dir(a)) # ['__doc__', '__module__']
print(dir(b)) # ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

print(b.__class__) # <class '__main__.B'>
print(type(b))     # <class '__main__.B'>

#####################
# The intersting part
print(a.__class__) # __main__.A
print(type(a))     # <type 'instance'>

print(B.__class__) # <type 'type'>
print(type(B))     # <type 'type'>

print(type(A))      # <type 'classobj'>
#print(A.__class__) # AttributeError: class A has no attribute '__class__'

Voir ce document pour plus d'informations :

Remarque : Les lignes données de cpython ont été modifiées en 2008 la dernière fois ( s'engager ), il semble donc qu'il s'agisse d'une question de compatibilité ou qu'ils l'aient simplement oubliée.

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