2016-08-09 8 views
0

Ich versuche herauszufinden, wie sichergestellt werden kann, dass eine Methode einer Klasse, die von einem ABC erbt, mit dem entsprechenden Decorator erstellt wird. Ich verstehe (hoffentlich), wie ABCs im Allgemeinen funktionieren.Erzwingen ABCs method decorators?

from abc import ABCMeta, abstractmethod 

class MyABC(metaclass=ABCMeta): 
    @abstractmethod 
    def my_abstract_method(self): 
     pass 

class MyClass(MyABC): 
    pass 

MyClass() 

Das gibt "Typeerror: nicht abstrakte Klasse MyClass mit abstrakten Methoden my_abstract_method instanziiert Can". Großartig, macht Sinn. Erstellen Sie einfach eine Methode mit diesem Namen.

class MyClass(MyABC): 
    def my_abstract_method(self): 
     pass 

MyClass() 

Boom. Sie sind fertig. Aber was ist mit diesem Fall?

Der MyClass() -Aufruf funktioniert, obwohl my_attribute keine Eigenschaft ist. Ich denke, am Ende stellen alle ABCs sicher, dass eine Methode mit einem bestimmten Namen existiert. Das ist es. Wenn Sie mehr davon möchten, müssen Sie sich den Quellcode von MyABC ansehen und die Dokumentation lesen. Die Dekoratoren und Kommentare dort werden Sie darüber informieren, wie Sie Ihre Unterklasse konstruieren müssen.

Habe ich es richtig oder fehle ich hier etwas?

+0

Dafür steht 'abstractproperty'. – user2357112

+0

'' abstractproperty'' war in Python 3.3 veraltet. OP hat die korrekte Verwendung für 3.3+; '' property'' und '' abstractmethod'' zusammen in der Basisklasse mit '' property'' in der Unterklasse. Sie können Unterklassen jedoch nicht implementieren, um sie korrekt zu implementieren. –

Antwort

1

Sie haben Recht, dass ABCs das nicht erzwingen. Es gibt keine Möglichkeit, etwas wie "hat einen bestimmten Dekorateur" durchzusetzen. Dekoratoren sind nur Funktionen, die Objekte zurückgeben (z. B. property gibt ein Eigenschaftsobjekt zurück). ABCMeta tut nichts, um sicherzustellen, dass die definierten Attribute in der Klasse etwas Bestimmtes sind; es stellt nur sicher, dass sie da sind. Dieses „Werk“ ohne Fehler:

class MyABC(metaclass=ABCMeta): 
    @abstractmethod 
    def my_abstract_method(self): 
     pass 

class MyClass(MyABC): 
    my_abstract_method = 2 

MyClass() 

Das heißt, ABCMeta nicht einmal sicher, dass die abstrakte Methode, wie auf der Unterklasse vorgesehen überhaupt ein Verfahren ist. Es muss nur ein Attribut irgendeiner Art mit diesem Namen sein,

Sie könnten sicherlich Ihre eigene Metaklasse schreiben, die ausgeklügelter prüft, um sicherzustellen, dass bestimmte Attribute bestimmte Arten von Werten haben, aber das ist außerhalb des Bereichs von ABCMeta.

+0

Danke. Ich dachte, dass ABCs genau nach einem bestimmten Dekorator suchen könnten, weil sie Klasseninstanzen zurückgeben (abhängig davon, wie sie definiert sind). Scheint wie isinstance() könnte verwendet werden, um die Kontrollen dort zu machen. Es ist alles gut. Ich habe versucht, über Möglichkeiten nachzudenken, wie ich meine "statischen" Fanboy-Mitarbeiter glücklich machen kann. Ich habe gelesen, dass ABCs verwendet werden können, um eine Schnittstelle zu erzwingen, aber das scheint nicht wirklich der Fall zu sein. – VagueAdvice

+0

@VagueAdvice: Was ich über Decorators sage ist, dass Sie nur erzwingen können, welche Art von Wert das Attribut hat, nicht ob dieser Wert über einen Decorator oder auf andere Weise erstellt wurde. (Aber das kannst du sowieso nicht mit ABCs machen.) Wenn du statische Fanboys befriedigen möchtest, solltest du dir vielleicht das neue 'typing' Modul ansehen. – BrenBarn

+0

Ich verstehe dich. Danke für den Tipp zum 'Tippen'. Ich machte Witze darüber, diese Kerle Fanboys zu nennen. Offensichtlich hat statische Typisierung große Vorteile. Wir schauen uns hier den Stack an und ich möchte auf Python setzen. Sie haben das als große Schwäche aufgefasst. Ich wollte nur sehen, was da draußen ist und auf ABCs stieß. Geben Sie Hinweise mit Mypy als Linter (zusammen mit den IDE-Warnungen) möglicherweise die Ursache. – VagueAdvice