`staticmethod` и` abc.abstractmethod`: Будет ли это сочетаться?
В моем приложении Python я хочу создать метод, который является как staticmethod
, так и abc.abstractmethod
. Как это сделать?
Я пробовал применять оба декоратора, но он не работает. Если я это сделаю:
import abc
class C(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
@staticmethod
def my_function(): pass
Я получаю исключение *, и если я это делаю:
class C(object):
__metaclass__ = abc.ABCMeta
@staticmethod
@abc.abstractmethod
def my_function(): pass
Абстрактный метод не применяется.
Как я могу сделать абстрактный статический метод?
* Исключение:
File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
Ответы
Ответ 1
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
Ответ 2
Начиная с Python 3.3, можно объединить @staticmethod
и @abstractmethod
, поэтому ни одно из других предложений не требуется больше:
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
Ответ 3
Это будет сделано:
>>> 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
Вы идете "Eh? It просто переименовывает @abstractmethod", и это совершенно правильно. Потому что любой подкласс из вышеперечисленного должен в любом случае включать в себя декоратор @staticmethod. Вам здесь не нужно этого, кроме как документации при чтении кода. Подкласс должен выглядеть следующим образом:
>>> class B(A):
... @staticmethod
... def themethod():
... print "Do whatevs"
Чтобы иметь функцию, которая заставит вас сделать этот метод статическим методом, вам придется подклассифицировать ABCmeta, чтобы проверить его и обеспечить его соблюдение. Это большая работа без реального возвращения. (Если кто-то забывает декоратор @staticmethod, он все равно получит ясную ошибку, он просто не упомянет статические методы.
Так на самом деле это работает так же хорошо:
>>> import abc
>>>
>>> class A(object):
... __metaclass__ = abc.ABCMeta
... @abc.abstractmethod
... def themethod():
... """Subclasses must implement this as a @staticmethod"""
... pass
Обновление - Другой способ объяснить это:
То, что метод является статическим элементом управления, как он называется.
Абстрактный метод никогда не вызывается.
Поэтому абстрактный статический метод является довольно бессмысленной концепцией, за исключением целей документации.
Ответ 4
В настоящее время это невозможно в Python 2.X, который будет только применять метод как абстрактный или статический, но не тот и другой.
В Python 3.2+ добавлены новые декораторы abc.abstractclassmethod
и abc.abstractstaticmethod
, чтобы объединить их применение как абстрактных, так и статических или абстрактных и метод класса.
См. Python Issue 5867