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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.