'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:Python26Libabc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
4 68

4 ответа:

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

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

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

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

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

обновление - еще один способ объяснить это:

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

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

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

посмотреть Python Выпуск 5867