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__'
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
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(...):
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.
This is currently not possible in Python 2.X, which will only enforce the method to be abstract or static, but not both.
In Python 3.2+, the new decoratorsabc.abstractclassmethod
and abc.abstractstaticmethod
were added to combine their enforcement of being abstract and static or abstract and a class method.
来源:https://stackoverflow.com/questions/4474395/staticmethod-and-abc-abstractmethod-will-it-blend