Maison >développement back-end >Tutoriel Python >Définir et utiliser des classes abstraites en Python
Tout le monde connaît les classes abstraites en Java. En Python, nous pouvons utiliser le module abc pour créer des classes abstraites. Nous expliquerons ici comment définir et utiliser des classes abstraites en Python
Python est comme Java. peut également définir une classe abstraite.
Avant de parler de classes abstraites, parlons de la mise en œuvre de méthodes abstraites.
Les méthodes abstraites sont des méthodes définies dans la classe de base mais sans aucune implémentation. En Java, vous pouvez déclarer une méthode comme interface. Le moyen simple d'implémenter une méthode abstraite en python est :
class Sheep(object): def get_size(self): raise NotImplementedError
Toute sous-classe héritée de Sheep doit implémenter la méthode get_size. Sinon, une erreur sera générée. Mais cette méthode de mise en œuvre présente un inconvénient. La sous-classe définie ne générera une erreur que lorsque cette méthode sera appelée. Voici un moyen simple de le déclencher une fois la classe instanciée. Utilisez le module abc fourni par python.
import abc class Sheep(object): __metaclass__ = abc.ABCMeta @abc.absractmethod def get_size(self): return
Une exception sera levée lors de l'instanciation de la classe Sheep ou de toute sous-classe héritée de celle-ci (get_size n'est pas implémenté).
Ainsi, en définissant une classe abstraite, vous pouvez définir des méthodes communes aux sous-classes (forçant leur implémentation).
Comment utiliser les classes abstraites
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def load(self, input): return @abc.abstractmethod def save(self, output, data): return
Créez une classe abstraite via la métaclasse ABCMeta et décorez-la avec abstractmethod Conteneur pour indiquer une méthode abstraite
Enregistrer une classe concrète
class B(object): def load(self, input): return input.read() def save(self, output, data): return output.write(data) A.register(B) if __name__ == '__main__': print issubclass(B, A) # print True print isinstance(B(), A) # print True
Enregistrer une classe concrète à partir d'un classe abstraite
Implémentation de sous-classe
class C(A): def load(self, input): return input.read() def save(self, output, data): return output.write(data) if __name__ == '__main__': print issubclass(C, A) # print True print isinstance(C(), A) # print True
Vous pouvez utiliser la méthode d'héritage de la classe abstraite pour implémenter la classe concrète. Cela peut éviter d'utiliser le registre. Mais l'effet secondaire est que vous pouvez trouver toutes les classes concrètes via la classe de base
for sc in A.__subclasses__(): print sc.__name__ # print C
Si vous utilisez l'héritage. , vous trouverez toutes les classes concrètes. Si vous utilisez register, elle ne sera pas trouvée
Utilisez __subclasshook__
Après avoir utilisé __subclasshook__, tant que la classe concrète définit le même méthode que la classe abstraite, elle sera considérée comme sa sous-classe
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def say(self): return 'say yeah' @classmethod def __subclasshook__(cls, C): if cls is A: if any("say" in B.__dict__ for B in C.__mro__): return True return NotTmplementd class B(object): def say(self): return 'hello' print issubclass(B, A) # True print isinstance(B(), A) # True print B.__dict__ # {'say': <function say at 0x7f...>, ...} print A.__subclasshook__(B) # True
Implémentation incomplète
class D(A): def save(self, output, data): return output.write(data) if __name__ == '__main__': print issubclass(D, A) # print True print isinstance(D(), A) # raise TypeError
Si vous construisez une classe concrète incomplète, elle lancera D. Impossible d'instancier des classes abstraites et des méthodes abstraites
Utiliser des classes de base abstraites dans des classes concrètes
import abc from cStringIO import StringIO class A(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def retrieve_values(self, input): pirnt 'base class reading data' return input.read() class B(A): def retrieve_values(self, input): base_data = super(B, self).retrieve_values(input) print 'subclass sorting data' response = sorted(base_data.splitlines()) return response input = StringIO("""line one line two line three """) reader = B() print reader.retrieve_values(input)
Imprimer les résultats
base class reading data subclass sorting data ['line one', 'line two', 'line three']
Vous pouvez utiliser super pour réutiliser la logique dans la classe de base abstraite, mais cela forcera l'enfant. La classe fournit des méthodes de substitution
Attribut abstrait
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'should never get here.' class B(A): @property def value(self): return 'concrete property.' try: a = A() print 'A.value', a.value except Exception, err: print 'Error: ', str(err) b = B() print 'B.value', b.value.
Imprimez le résultat, A ne peut pas être instancié car il n'y a qu'une seule méthode d'obtention de propriété abstraite.
Error: ... print concrete property
Définir la lecture et l'écriture abstraites propriétés
import abc class A(object): __metaclass__ = abc.ABCMeta def value_getter(self): return 'Should never see this.' def value_setter(self, value): return value = abc.abstractproperty(value_getter, value_setter) class B(A): @abc.abstractproperty def value(self): return 'read-only' class C(A): _value = 'default value' def value_getter(self): return self._value def value_setter(self, value): self._value = value value = property(value_getter, value_setter) try: a = A() print a.value except Exception, err: print str(err) try: b = B() print b.value except Exception, err: print str(err) c = C() print c.value c.value = 'hello' print c.value
Imprimer le résultat Lors de la définition de la propriété de la classe concrète, elle doit être la même que la propriété abstraite. Cela ne fonctionnera pas si vous n'en remplacez qu'un seul
error: ... error: ... print 'default value' print 'hello'
Utilisez la syntaxe du décorateur pour implémenter les propriétés abstraites de lecture et d'écriture. l'écriture devrait être la même .
import abc class A(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'should never see this.' @value.setter def value(self, _value): return class B(A): _value = 'default' @property def value(self): return self._value @value.setter def value(self, _value): self._value = _value b = B() print b.value # print 'default' b.value = 'hello' print b.value # print 'hello'
Pour plus d'articles liés à la définition et à l'utilisation de classes abstraites en Python, veuillez faites attention au site Web PHP chinois !