`staticmethod` и` abc.abstractmethod`: смешается ли это? - PullRequest
77 голосов
/ 17 декабря 2010

В моем приложении 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__'

Ответы [ 4 ]

114 голосов
/ 23 июля 2015

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

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
30 голосов
/ 17 декабря 2010
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
12 голосов
/ 18 декабря 2010

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

  >>> 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 голосов
/ 18 сентября 2012

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

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

См. Python Issue 5867

...