`staticmethod` and `abc.abstractmethod`: Will it blend?
In my Python app I want to make a method that is both a staticmethod
and an abc.abstractmethod
. How do I do this?
I tried applying both decorators, but it doesn't work. If I do this:
import abc
class C(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
@staticmethod
def my_function(): pass
I get an exception*, and if I do this:
class C(object):
__metaclass__ = abc.ABCMeta
@staticmethod
@abc.abstractmethod
def my_function(): pass
The abstract method is not enforced.
How can I make an abstract static method?
*The exception:
File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
Starting with Python 3.3, it is possible to combine @staticmethod
and @abstractmethod
, so none of the other suggestions are necessary anymore:
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
Further @abstractstatic
is deprecated since version 3.3.
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
This will do it:
>>> 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
You go "Eh? It just renames @abstractmethod", and this is completely correct. Because any subclass of the above will have to include the @staticmethod decorator anyway. You have no need of it here, except as documentation when reading the code. A subclass would have to look like this:
>>> class B(A):
... @staticmethod
... def themethod():
... print "Do whatevs"
To have a function that would enforce you to make this method a static method you would have to subclass ABCmeta to check for that and enforce it. That's a lot of work for no real return. (If somebody forgets the @staticmethod decorator they will get a clear error anyway, it just won't mention static methods.
So in fact this works just as well:
>>> import abc
>>>
>>> class A(object):
... __metaclass__ = abc.ABCMeta
... @abc.abstractmethod
... def themethod():
... """Subclasses must implement this as a @staticmethod"""
... pass
Update - Another way to explain it:
That a method is static controls how it is called. An abstract method is never called. And abstract static method is therefore a pretty pointless concept, except for documentation purposes.