Подтвердить что ты не робот

`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__'
4b9b3361

Ответ 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