`staticmethod` и `abc.abstractmethod`: будут ли они сочетаться?


person Ram Rachum    schedule 17.12.2010    source источник


Ответы (4)


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

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):

Далее @abstractstatic устарел, начиная с версии 3.3.

person gerrit    schedule 23.07.2015
comment
Обратите внимание, что вы должны поставить @staticmethod первым, иначе вы получите AttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable - person Marco Sulla; 05.12.2016
comment
То же самое для @property - person zezollo; 04.08.2017
comment
Было бы очень полезно, если бы это был принятый ответ! - person Keerthana Prabhakaran; 14.05.2018
comment
Именно то, что я искал. Спасибо! - person shanu khera; 07.04.2020
comment
Да, и порядок имеет значение, если вы сначала напишете @abstractmethod, это не сработает. - person HARSH NILESH PATHAK; 24.11.2020

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

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

Обновление. Другой способ объяснить это:

То, что метод является статическим, определяет, как он вызывается. Абстрактный метод никогда не вызывается. И поэтому абстрактный статический метод является довольно бессмысленной концепцией, за исключением целей документации.

person Lennart Regebro    schedule 18.12.2010

В настоящее время это невозможно в Python 2.X, в котором метод будет только абстрактным или статическим, но не тем и другим одновременно.

В Python 3.2+ были добавлены новые декораторыabc.abstractclassmethod и abc.abstractstaticmethod, чтобы объединить принудительное выполнение абстрактного и статического или абстрактного и метода класса.

См. ошибку Python 5867.

person Nick    schedule 18.09.2012
comment
В то время как новые в Python 3.2, abstractclassmethod и abstractstaticmethod быстро устарели в Python 3.3, а также abstractproperty. docs.python.org/3/library/abc.html - person glarrain; 12.05.2013
comment
К вашему сведению: bugs.python.org/issue11610 описывает удаление и новый способ сделать это... - person FlipMcF; 02.08.2013

person    schedule
comment
Хорошо сыграно, сэр или мадам :-) Вы пропустили import abc вверху; а также подкласс, который показывает реализацию A. (например, class B(A):\n @staticmethod\n def test():\n print 10\n) - person Dan Breslau; 17.12.2010
comment
Я обновил код для правильной работы с подклассами. A.test также должен иметь атрибут __isabstractmethod__. - person Rosh Oxymoron; 17.12.2010
comment
Должен ли abstractstatic быть добавлен выше по течению к abc.py? - person nnyby; 03.03.2015
comment
abstractstaticmethod Устарело, начиная с версии 3.3: теперь можно использовать staticmethod с abstractmethod(), что делает этот декоратор излишним. ссылка - person irakli khitarishvili; 24.12.2015
comment
@iraklikhitarishvili Тем не менее, это не означает, что метод подкласса должен быть статическим! Вы должны продублировать декоратор статического метода... Нет ли способа обойти это? - person étale-cohomology; 11.03.2016
comment
@DiegoAlonsoCortez Извините за поздний ответ. Я предпочитаю писать @staticmethod для каждой реализации. но если вы хотите, вы можете создать подкласс ABCMeta и переопределить метод __new__, чтобы проверить, является ли метод базового класса статическим, и если это так, то сделать дочерний метод также статическим. пример. но мне не нравится такой подход. – - person irakli khitarishvili; 14.03.2016
comment
Извините, пришлось -1 за то, что не добавил никаких объяснений - person Amit Tripathi; 20.06.2018