Heim  >  Artikel  >  Backend-Entwicklung  >  Definieren und Verwenden abstrakter Klassen in Python

Definieren und Verwenden abstrakter Klassen in Python

高洛峰
高洛峰Original
2017-03-01 13:49:161408Durchsuche

Jeder ist mit abstrakten Klassen in Java vertraut. Wir können das ABC-Modul verwenden, um abstrakte Klassen in Python zu erstellen.

Python ist wie Java kann auch eine abstrakte Klasse definieren.

Bevor wir über abstrakte Klassen sprechen, sprechen wir über die Implementierung abstrakter Methoden.

Abstrakte Methoden sind in der Basisklasse definierte Methoden, jedoch ohne Implementierung. In Java können Sie eine Methode als Schnittstelle deklarieren. Der einfache Weg, eine abstrakte Methode in Python zu implementieren, ist:

class Sheep(object):
  def get_size(self):
    raise NotImplementedError

Jede von Sheep geerbte Unterklasse muss die Methode get_size implementieren. Andernfalls wird ein Fehler generiert. Diese Implementierungsmethode hat jedoch einen Nachteil. Die definierte Unterklasse gibt nur dann einen Fehler aus, wenn diese Methode aufgerufen wird. Hier ist eine einfache Möglichkeit, es auszulösen, nachdem die Klasse instanziiert wurde. Verwenden Sie das von Python bereitgestellte abc-Modul.

import abc
class Sheep(object):
  __metaclass__ = abc.ABCMeta
  
  @abc.absractmethod
  def get_size(self):
    return


Eine Ausnahme wird ausgelöst, wenn die Sheep-Klasse oder eine davon geerbte Unterklasse instanziiert wird (get_size ist nicht implementiert).

Somit können Sie durch die Definition einer abstrakten Klasse gemeinsame Methoden für Unterklassen definieren (und so deren Implementierung erzwingen).

So verwenden Sie abstrakte Klassen

import abc 

class A(object):
  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def load(self, input):
    return 

  @abc.abstractmethod
  def save(self, output, data):
    return

Erstellen Sie eine abstrakte Klasse über die ABCMeta-Metaklasse und dekorieren Sie sie mit abstractmethod Container zur Angabe einer abstrakten Methode

Eine konkrete Klasse registrieren

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

Eine konkrete Klasse aus einer registrieren abstrakte Klasse

Unterklassenimplementierung

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

Sie können die Methode der Vererbung der abstrakten Klasse verwenden, um die zu implementieren Konkrete Klasse. Dies kann die Verwendung von Registern vermeiden. Der Nebeneffekt ist jedoch, dass Sie alle konkreten Klassen über die Basisklasse finden können

for sc in A.__subclasses__():
  print sc.__name__

# print C

Wenn Sie Vererbung verwenden , finden Sie alle konkreten Klassen. Wenn Sie „register“ verwenden, wird es nicht gefunden.

Verwenden Sie __subclasshook__

Nach der Verwendung von __subclasshook__, solange die konkrete Klasse die definiert Dieselbe Methode wie die abstrakte Klasse, sie wird berücksichtigt Ist seine Unterklasse

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

Unvollständige Implementierung

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

Wenn Sie eine unvollständige konkrete Klasse erstellen, wird D ausgegeben. Abstrakte Klassen und abstrakte Methoden können nicht instanziiert werden

Abstrakte Basisklassen in konkreten Klassen verwenden

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)

Ergebnisse drucken

base class reading data
subclass sorting data
[&#39;line one&#39;, &#39;line two&#39;, &#39;line three&#39;]

Sie können super verwenden, um die Logik wiederzuverwenden in der abstrakten Basisklasse, aber es wird die untergeordnete Klasse zwingen, überschreibende Methoden bereitzustellen

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
Drucken Sie das Ergebnis aus. A kann nicht instanziiert werden, da es nur eine Getter-Methode für abstrakte Eigenschaften gibt.

Error: ...
print concrete property

Abstraktes Lesen und Schreiben definieren Eigenschaften

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
Wenn Sie die Eigenschaft der konkreten Klasse definieren, muss sie mit der abstrakten Eigenschaft identisch sein. Es funktioniert nicht, wenn Sie nur eine davon überschreiben.

error: ...
error: ...
print &#39;default value&#39;
print &#39;hello&#39;
Verwenden Sie die Decorator-Syntax, um abstrakte Eigenschaften zum Lesen und Schreiben zu implementieren Das Schreiben sollte dasselbe sein.

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;


Weitere Artikel zum Definieren und Verwenden abstrakter Klassen in Python finden Sie bitte Achten Sie auf die chinesische PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn