Définir et utiliser des classes abstraites en Python

高洛峰
Libérer: 2017-03-01 13:49:16
original
1456 Les gens l'ont consulté

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
Copier après la connexion

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
Copier après la connexion


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
Copier après la connexion

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
Copier après la connexion

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
Copier après la connexion

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
Copier après la connexion

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__      # {&#39;say&#39;: <function say at 0x7f...>, ...}
print A.__subclasshook__(B) # True
Copier après la connexion

Implémentation incomplète

class D(A):
  def save(self, output, data):
    return output.write(data)

if __name__ == &#39;__main__&#39;:
  print issubclass(D, A)   # print True
  print isinstance(D(), A)  # raise TypeError
Copier après la connexion

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 &#39;base class reading data&#39;
    return input.read()


class B(A):

  def retrieve_values(self, input):
    base_data = super(B, self).retrieve_values(input)
    print &#39;subclass sorting data&#39;
    response = sorted(base_data.splitlines())
    return response

input = StringIO("""line one
line two
line three
""")

reader = B()
print reader.retrieve_values(input)
Copier après la connexion

Imprimer les résultats

base class reading data
subclass sorting data
[&#39;line one&#39;, &#39;line two&#39;, &#39;line three&#39;]
Copier après la connexion

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 &#39;should never get here.&#39;

class B(A):
  
  @property
  def value(self):
    return &#39;concrete property.&#39;

try:
  a = A()
  print &#39;A.value&#39;, a.value
except Exception, err:
  print &#39;Error: &#39;, str(err)

b = B()
print &#39;B.value&#39;, b.value
Copier après la connexion

.

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
Copier après la connexion

Définir la lecture et l'écriture abstraites propriétés

import abc

class A(object):
  __metaclass__ = abc.ABCMeta

  def value_getter(self):
    return &#39;Should never see this.&#39;

  def value_setter(self, value):
    return 

  value = abc.abstractproperty(value_getter, value_setter)

class B(A):
  
  @abc.abstractproperty
  def value(self):
    return &#39;read-only&#39;

class C(A):
  _value = &#39;default value&#39;

  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 = &#39;hello&#39;
print c.value
Copier après la connexion

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 &#39;default value&#39;
print &#39;hello&#39;
Copier après la connexion

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 &#39;should never see this.&#39;

  @value.setter
  def value(self, _value):
    return 

class B(A):
  _value = &#39;default&#39;

  @property
  def value(self):
    return self._value

  @value.setter
  def value(self, _value):
    self._value = _value

b = B()
print b.value    # print &#39;default&#39;

b.value = &#39;hello&#39;
print b.value    # print &#39;hello&#39;
Copier après la connexion


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 !

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!