web-dev-qa-db-fra.com

Comment vérifier (au moment de l'exécution) si une classe est une sous-classe d'une autre?

Disons que j'ai un costume de classe et quatre sous-classes de costume: Heart, Spade, Diamond, Club.

class Suit:
   ...
class Heart(Suit):
   ...
class Spade(Suit):
   ...
class Diamond(Suit):
   ...
class Club(Suit):
   ...

J'ai une méthode qui reçoit un costume en tant que paramètre, qui est un objet de classe et non une instance. Plus précisément, il peut ne recevoir qu'une des quatre valeurs: Cœur, Pique, Diamant, Club. Comment puis-je faire une affirmation qui assure une telle chose? Quelque chose comme:

def my_method(suit):
   assert(suit subclass of Suit)
   ...

J'utilise Python 3.

149
snakile

Vous pouvez utiliser issubclass() comme ceci assert issubclass(suit, Suit).

170
user97370

issubclass(class, classinfo)

Extrait:

Renvoie true si class est une sous-classe (directe, indirecte ou virtuelle) de classinfo.

37
Katriel

Vous pouvez utiliser isinstance si vous avez une instance, ou issubclass si vous avez une classe. Normalement pensé que c'est une mauvaise idée. Normalement, en Python, vous déterminez si un objet est capable de quelque chose en essayant de le faire.

25
David Heffernan

La fonction booléenne issubclass(sub, sup) renvoie true si la sous-classe sub donnée est bien une sous-classe de la superclasse sup.

19
Jameer Mulani

Utiliser issubclass semblait être un moyen simple d'écrire des niveaux de log. Cela fait un peu bizarre de l'utiliser ... mais cela semble plus propre que les autres options. 

class Error(object): pass
class Warn(Error): pass
class Info(Warn): pass
class Debug(Info): pass

class Logger():
    LEVEL = Info

    @staticmethod
    def log(text,level):
        if issubclass(Logger.LEVEL,level):
            print(text)
    @staticmethod
    def debug(text):
        Logger.log(text,Debug)   
    @staticmethod
    def info(text):
        Logger.log(text,Info)
    @staticmethod
    def warn(text):
        Logger.log(text,Warn)
    @staticmethod
    def error(text):
        Logger.log(text,Error)
1
Jon Donnelly

Vous pouvez utiliser la classe issub intégrée. Mais la vérification de type est généralement considérée comme inutile, car vous pouvez utiliser le typage de canard.

1
XORcist

Selon le doc Python , nous pouvons également utiliser l'attribut class.__mro__ ou la méthode class.mro():

class Suit:
    pass
class Heart(Suit):
    pass
class Spade(Suit):
    pass
class Diamond(Suit):
    pass
class Club(Suit):
    pass

>>> Heart.mro()
[<class '__main__.Heart'>, <class '__main__.Suit'>, <class 'object'>]
>>> Heart.__mro__
(<class '__main__.Heart'>, <class '__main__.Suit'>, <class 'object'>)

Suit in Heart.mro()  # True
object in Heart.__mro__  # True
Spade in Heart.mro()  # False
0
YaOzI

Exemple minimal exécutable

Voici un exemple plus complet avec quelques assertions:

#!/usr/bin/env python3

class Base:
    pass

class Derived(Base):
    pass

base = Base()
derived = Derived()

# Basic usage.
assert issubclass(Derived, Base)
assert not issubclass(Base, Derived)

# True for same object.
assert issubclass(Base, Base)

# Cannot use object of class.
try:
    issubclass(derived, Base)
except TypeError:
    pass
else:
    assert False

# Do this instead.
assert isinstance(derived, Base)

GitHub en amont .

Testé en Python 3.5.2.