staticmethod и abc.abstractmethod: будет ли он смешиваться?

107

В моем приложении 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__'
Рам Рахум
источник
5
Обновите принятый ответ.
Neil G

Ответы:

34
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
Рош Оксюморон
источник
7
Хорошо сыграно, сэр или мадам :-) Вы не попали import abcна первое место; а также подкласс, который показывает экземпляр A. (например, class B(A):\n @staticmethod\n def test():\n print 10\n)
Дэн Бреслау
1
Я обновил код для правильной работы с подклассами. A.test также должен иметь __isabstractmethod__атрибут.
Рош Оксюморон
3
Следует abstractstaticдобавить вверх по течению к abc.py?
nnyby 03
3
abstractstaticmethod Не рекомендуется, начиная с версии 3.3: теперь можно использовать staticmethod с abstractmethod (), что делает этот декоратор избыточным. ссылка
иракли хитаришвили
1
@iraklikhitarishvili Тем не менее, это не заставляет метод подкласса быть статическим! Вы должны продублировать декоратор staticmethod ... Ничего подобного?
étale-cohomology
201

Начиная с Python 3.3 , можно комбинировать @staticmethod и @abstractmethod, поэтому больше не нужны никакие другие предложения:

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
геррит
источник
34
Обратите внимание, что вы должны поставить @staticmethodпервым, иначе вы получитеAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Марко Сулла
3
То же самое для@property
zezollo
11
Было бы очень полезно, если бы это был принятый ответ!
Киртхана Прабхакаран
Именно то, что я искал. Спасибо!
шану кхера
13

Это сделает это:

  >>> 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

Вы говорите: «А? Он просто переименовывает @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 5867

Ник
источник
11
Хотя это было впервые в Python 3.2 abstractclassmethodи abstractstaticmethodбыстро устарело в Python 3.3, а также abstractproperty. docs.python.org/3/library/abc.html
glarrain
4
К вашему сведению: bugs.python.org/issue11610 описывает деприкацию и новый способ сделать это ...
FlipMcF 01