`staticmethod` und` abc.abstractmethod`: Wird es gemischt?

105

In meiner Python-App möchte ich eine Methode erstellen, die sowohl a staticmethodals auch an ist abc.abstractmethod. Wie mache ich das?

Ich habe versucht, beide Dekorateure anzuwenden, aber es funktioniert nicht. Wenn ich das mache:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @staticmethod    
    def my_function(): pass

Ich bekomme eine Ausnahme * und wenn ich das mache:

class C(object):
    __metaclass__ = abc.ABCMeta

    @staticmethod    
    @abc.abstractmethod
    def my_function(): pass

Die abstrakte Methode wird nicht erzwungen.

Wie kann ich eine abstrakte statische Methode erstellen?

*Die Ausnahme:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
Ram Rachum
quelle
5
Bitte aktualisieren Sie Ihre akzeptierte Antwort.
Neil G

Antworten:

34
class abstractstatic(staticmethod):
    __slots__ = ()
    def __init__(self, function):
        super(abstractstatic, self).__init__(function)
        function.__isabstractmethod__ = True
    __isabstractmethod__ = True

class A(object):
    __metaclass__ = abc.ABCMeta
    @abstractstatic
    def test():
        print 5
Rosh Oxymoron
quelle
7
Gut gespielt, Sir oder Madam :-) Sie haben oben ausgelassen import abc; sowie eine Unterklasse, die die Instanziierung von A. (z. B. class B(A):\n @staticmethod\n def test():\n print 10\n) zeigt
Dan Breslau
1
Ich habe den Code aktualisiert, damit er ordnungsgemäß mit Unterklassen funktioniert. A.test sollte auch das __isabstractmethod__Attribut haben.
Rosh Oxymoron
3
Sollte abstractstaticvorgeschaltet werden abc.py?
nnyby
3
abstractstaticmethod Veraltet seit Version 3.3: Es ist jetzt möglich, staticmethod mit abstractmethod () zu verwenden, wodurch dieser Dekorator überflüssig wird. Link
irakli khitarishvili
1
@iraklikhitarishvili Trotzdem erzwingt das nicht, dass die Methode der Unterklasse statisch ist! Sie müssen den statischen Methodendekorator duplizieren ... Gibt es keinen Weg daran vorbei?
-Kohomologie
196

Ab Python 3.3 ist es möglich, @staticmethod und @abstractmethoddaher ist keiner der anderen Vorschläge mehr erforderlich:

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
gerrit
quelle
31
Beachten Sie, dass Sie @staticmethodals erstes setzen müssen, sonst erhalten SieAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Marco Sulla
3
Gleiches gilt für@property
Zezollo
11
Es wäre wirklich hilfreich, wenn dies die akzeptierte Antwort wäre!
Keerthana Prabhakaran
Genau das, wonach ich gesucht habe. Vielen Dank!
Shanu Khera
13

Dies wird es tun:

  >>> import abc
  >>> abstractstaticmethod = abc.abstractmethod
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abstractstaticmethod
  ...     def themethod():
  ...          pass
  ... 
  >>> a = A()
  >>> Traceback (most recent call last):
  File "asm.py", line 16, in <module>
    a = A()
  TypeError: Can't instantiate abstract class A with abstract methods test

Sie gehen zu "Eh? Es benennt nur @abstractmethod um", und das ist völlig richtig. Weil jede Unterklasse der oben genannten sowieso den @ staticmethod-Dekorator enthalten muss. Sie brauchen es hier nicht, außer als Dokumentation beim Lesen des Codes. Eine Unterklasse müsste folgendermaßen aussehen:

  >>> class B(A):
  ...     @staticmethod
  ...     def themethod():
  ...         print "Do whatevs"

Um eine Funktion zu haben, die Sie dazu zwingen würde, diese Methode zu einer statischen Methode zu machen, müssten Sie ABCmeta in eine Unterklasse unterteilen, um dies zu überprüfen und zu erzwingen. Das ist viel Arbeit für keine wirkliche Rückkehr. (Wenn jemand den @ staticmethod-Dekorator vergisst, wird ohnehin ein klarer Fehler angezeigt, statische Methoden werden nur nicht erwähnt.

Tatsächlich funktioniert das also genauso gut:

  >>> import abc
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abc.abstractmethod
  ...     def themethod():
  ...         """Subclasses must implement this as a @staticmethod"""
  ...          pass

Update - Eine andere Möglichkeit, es zu erklären:

Dass eine Methode statisch ist, steuert, wie sie aufgerufen wird. Eine abstrakte Methode wird niemals aufgerufen. Und abstrakte statische Methoden sind daher ein ziemlich sinnloses Konzept, außer zu Dokumentationszwecken.

Lennart Regebro
quelle
4

Dies ist derzeit in Python 2.X nicht möglich, wodurch die Methode nur abstrakt oder statisch erzwungen wird, nicht jedoch beide.

In Python 3.2+ wurden die neuen Dekoratoren abc.abstractclassmethodund abc.abstractstaticmethodhinzugefügt, um ihre Durchsetzung von abstrakt und statisch oder abstrakt und eine Klassenmethode zu kombinieren.

Siehe Python-Ausgabe 5867

Nick
quelle
11
Während neu in Python 3.2 abstractclassmethodund abstractstaticmethodwurden in Python 3.3 sowie schnell veraltet abstractproperty. docs.python.org/3/library/abc.html
Glarrain
4
Zu Ihrer Information : bugs.python.org/issue11610 beschreibt die Entbehrung und den neuen Weg, dies zu tun ...
FlipMcF