In mijn Python-app wil ik een methode maken die zowel een staticmethod
als een abc.abstractmethod
. Hoe doe ik dit?
Ik heb geprobeerd beide decorateurs toe te passen, maar het werkt niet. Als ik dit doe:
import abc
class C(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
@staticmethod
def my_function(): pass
Ik krijg een uitzondering*, en als ik dit doe:
class C(object):
__metaclass__ = abc.ABCMeta
@staticmethod
@abc.abstractmethod
def my_function(): pass
De abstracte methode wordt niet afgedwongen.
Hoe kan ik een abstracte statische methode maken?
*De uitzondering:
File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
Antwoord 1, autoriteit 100%
Vanaf Python 3.3is het mogelijk om@staticmethod
en @abstractmethod
te combineren, zodat geen van de andere suggesties meer nodig is:
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
Verdere @abstractstatic
is verouderd sinds versie 3.3.
Antwoord 2, autoriteit 13%
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
Antwoord 3, autoriteit 5%
Dit zal het doen:
>>> 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
Je zegt “Eh? Het hernoemt gewoon @abstractmethod”, en dit is helemaal correct. Omdat elke subklasse van het bovenstaande sowieso de @staticmethod-decorateur moet bevatten. Je hebt het hier niet nodig, behalve als documentatie bij het lezen van de code. Een subklasse zou er als volgt uit moeten zien:
>>> class B(A):
... @staticmethod
... def themethod():
... print "Do whatevs"
Om een functie te hebben die je zou dwingen om van deze methode een statische methode te maken, zou je ABCmeta moeten subclasseren om daarop te controleren en het af te dwingen. Dat is veel werk zonder echt rendement. (Als iemand de @staticmethod-decorateur vergeet, krijgen ze sowieso een duidelijke foutmelding, alleen worden statische methoden niet genoemd.
Dus in feite werkt dit net zo goed:
>>> import abc
>>>
>>> class A(object):
... __metaclass__ = abc.ABCMeta
... @abc.abstractmethod
... def themethod():
... """Subclasses must implement this as a @staticmethod"""
... pass
Update – Een andere manier om het uit te leggen:
Dat een methode statisch is, bepaalt hoe deze wordt aangeroepen.
Een abstracte methode wordt nooit aangeroepen.
En abstracte statische methode is daarom een vrij zinloos concept, behalve voor documentatiedoeleinden.
Antwoord 4
Dit is momenteel niet mogelijk in Python 2.X, waardoor de methode alleen abstract of statisch is, maar niet beide.
In Python 3.2+ zijn de nieuwe decorateursabc.abstractclassmethod
en abc.abstractstaticmethod
toegevoegd om hun handhaving van abstract en statisch of abstract en een klassenmethode te combineren.