`staticmethod` та` abc.abriefmethod`: Чи буде він поєднуватися?


106

У своєму додатку Python я хочу зробити метод, який є і a, staticmethodі an 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
Оновіть прийняту відповідь.
Ніл Г

Відповіді:


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на вершині; а також підклас, який показує примірник А. (наприклад, class B(A):\n @staticmethod\n def test():\n print 10\n)
Дан Бреслау

1
Я оновив код для належної роботи з підкласами. A.test також повинен мати __isabstractmethod__атрибут.
Рош Оксиморон

3
Чи abstractstaticслід додати до потоку abc.py?
nnyby

3
абстрактний статичний метод застарілий з версії 3.3: Тепер можна використовувати статичний метод з абстрактним методом (), що робить цей декоратор зайвим. посилання
irakli kititarishvili

1
@iraklikhitarishvili Тим не менш, це не примушує метод підкласу бути статичним! Ви повинні дублювати декоратор статичного методу ... Чи не обійтись?
étale-когомологія

199

Починаючи з Python 3.3 , можна комбінувати @staticmethod і @abstractmethod, тому жодна з інших пропозицій більше не потрібна:

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

32
Зауважте, що ви повинні поставити @staticmethodяк перше, інакше ви отримаєтеAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Марко Сулла

3
Те саме для@property
zezollo

11
Було б дуже корисно, якби це була прийнята відповідь!
Кеертана Прабхакаран

Саме те, що я шукав. Дякую!
shanu khera

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

Ви переходите до "Е? Це просто перейменовано @ab абстрактmethod", і це абсолютно правильно. Тому що будь-який підклас вищевказаного повинен буде так чи інакше включати декоратор @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
FYI: bugs.python.org/issue11610 описує зображення і новий спосіб зробити це
FlipMcF
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.