111 votes

Python décoration @abstractmethod

J'ai lu la documentation Python sur les classes de base abstraites :

De ici :

abc.abstractmethod(fonction) Un décorateur indiquant des méthodes abstraites.

L'utilisation de ce décorateur nécessite que la métaclass de la classe soit ABCMeta ou en soit dérivée. Une classe ayant une métaclass dérivée de ABCMeta ne peut pas être instanciée à moins que toutes ses méthodes abstraites et propriétés soient redéfinies.

Et ici

Vous pouvez appliquer le décorateur @abstractmethod aux méthodes telles que draw() qui doivent être implémentées; Python lèvera alors une exception pour les classes qui ne définissent pas la méthode. Notez que l'exception n'est levée que lorsque vous essayez réellement de créer une instance d'une sous-classe qui manque de la méthode.

J'ai utilisé ce code pour tester cela :

import abc

class AbstractClass(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def abstractMethod(self):
    return

class ConcreteClass(AbstractClass):
  def __init__(self):
    self.me = "me"

c = ConcreteClass()
c.abstractMethod()

Le code fonctionne bien, donc je ne comprends pas. Si je tape c.abstractMethod j'obtiens :

>

Qu'est-ce que je rate ici ? ConcreteClass doit implémenter les méthodes abstraites, mais je n'ai aucune exception.

122voto

mouad Points 21520

Utilisez-vous python3 pour exécuter ce code? Si oui, sachez que déclarer une métaclasse en python3 a changé, vous devriez le faire comme ceci à la place :

import abc

class AbstractClass(metaclass=abc.ABCMeta):

  @abc.abstractmethod
  def abstractMethod(self):
      return

Le code complet et l'explication derrière la réponse sont les suivants :

import abc

class AbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def abstractMethod(self):
        return

class ConcreteClass(AbstractClass):

    def __init__(self):
        self.me = "me"

# Obtenez une TypeError sans les deux lignes suivantes :
#   def abstractMethod(self):
#       return 0

c = ConcreteClass()
c.abstractMethod()

Si abstractMethod n'est pas définie pour ConcreteClass, l'exception suivante sera levée lors de l'exécution du code ci-dessus : TypeError: Can't instantiate abstract class ConcreteClass with abstract methods abstractMethod

26voto

l001d Points 93

Importer ABC de abc et faire de votre propre classe abstraite un enfant de ABC peut aider à rendre le code plus propre.

from abc import ABC, abstractmethod

class AbstractClass(ABC):

  @abstractmethod
  def abstractMethod(self):
    return

class ConcreteClass(AbstractClass):
  def __init__(self):
    self.me = "me"

# La ligne suivante déclencherait une TypeError signalant
# que abstractMethod n'est pas implémenté
c = ConcreteClass()

Testé avec Python 3.6

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