web-dev-qa-db-fra.com

Quel est le but de la vérification de soi .__ classe__? - python

Quel est le but de vérifier self.__class__? J'ai trouvé du code qui crée une classe d'interface abstraite et vérifie ensuite si son self.__class__ est lui-même, par exemple.

class abstract1 (object):
  def __init__(self):
    if self.__class__ == abstract1: 
      raise NotImplementedError("Interfaces can't be instantiated")

Quel est le but de cela? Est-ce pour vérifier si la classe est un type d'elle-même?

Le code provient de NLTK http://nltk.googlecode.com/svn/trunk/doc/api/nltk.probability-pysrc.html#ProbDistI

19
alvas

self.__class__ Est une référence au type de l'instance actuelle.

Pour les instances de abstract1, Ce serait la classe abstract1 elle-même , ce que vous ne voulez pas avec une classe abstraite. Les classes abstraites sont uniquement destinées à être sous-classées, pas à créer directement des instances:

>>> abstract1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
NotImplementedError: Interfaces can't be instantiated

Pour une instance d'une sous-classe de abstract1, self.__class__ Serait une référence à la sous-classe spécifique:

>>> class Foo(abstract1): pass
... 
>>> f = Foo()
>>> f.__class__
<class '__main__.Foo'>
>>> f.__class__ is Foo
True

Lancer une exception ici, c'est comme utiliser une instruction assert ailleurs dans votre code, cela vous protège contre les erreurs idiotes.

Notez que la méthode Pythonic pour tester le type d'une instance consiste à utiliser la fonction type() à la place, avec un test d'identité avec l'opérateur is:

class abstract1(object):
    def __init__(self):
        if type(self) is abstract1: 
            raise NotImplementedError("Interfaces can't be instantiated")

type() doit être préféré à self.__class__ car ce dernier peut être masqué par un attribut de classe .

Il n'y a aucun intérêt à utiliser un test d'égalité ici comme pour les classes personnalisées, __eq__ Est de toute façon implémenté comme un test d'identité.

Python comprend également une bibliothèque standard pour définir des classes de base abstraites, appelée abc . Il vous permet de marquer des méthodes et des propriétés comme abstraites et refusera de créer des instances de toute sous-classe qui n'a pas encore redéfini ces noms.

23
Martijn Pieters

Le code que vous avez affiché là-bas est un no-op; self.__class__ == c1 ne fait pas partie d'un conditionnel donc le booléen est évalué mais rien n'est fait avec le résultat.

Vous pouvez essayer de créer une classe de base abstraite qui vérifie si self.__class__ est égal à la classe abstraite par opposition à un enfant hypothétique (via une instruction if), afin d'empêcher l'instanciation de la classe de base abstraite elle-même en raison d'une erreur de développeur.

1
Andrew Gorcester

Je dirais que certains feraient:

class Foo(AbstractBase):
    def __init__(self):
        super(Foo, self).__init__()
        # ...

Même lorsque la base est abstraite, vous ne voudriez pas que la base __init__ pour lancer NotImplementedError. Hé, peut-être que ça fait même quelque chose d'utile?

1
Kos

Quel est le but de cela? Est-ce pour vérifier si la classe est un type d'elle-même?

Oui, si vous essayez de construire un objet de type Abstract1 cela va lever cette exception vous disant que vous n'êtes pas autorisé à le faire.

1
That Umbrella Guy

Dans Python 3 soit en utilisant type() pour vérifier le type ou __class__ renverra le même résultat.

class C:pass
ci=C()
print(type(ci)) #<class '__main__.C'>
print(ci.__class__) #<class '__main__.C'>

J'ai récemment vérifié le implémentation pour le @dataclass décorateur (Raymond Hettinger est directement impliqué dans ce projet), et ils utilisent __class__ pour faire référence au type.

Il n'est donc pas faux d'utiliser __class__ :)

0
prosti

Les indices se trouvent au nom de la classe, "abstract1", et dans l'erreur. Il s'agit d'une classe abstraite, c'est-à-dire d'une classe destinée à être sous-classée. Chaque sous-classe fournira son propre comportement. La classe abstraite elle-même sert à documenter l'interface, c'est-à-dire les méthodes et les arguments que les classes implémentant l'interface devraient avoir. Il n'est pas censé être instancié lui-même, et le test est utilisé pour dire si nous sommes dans la classe elle-même ou dans une sous-classe.

Voir la section sur les classes abstraites dans ce article par Julien Danjou.

0
Peter Westlake