web-dev-qa-db-fra.com

`staticmethod` et` abc.abstractmethod`: Va-t-il se fondre?

Dans mon application Python je veux créer une méthode qui soit à la fois staticmethod et abc.abstractmethod . Comment puis-je faire cela?

J'ai essayé d'appliquer les deux décorateurs, mais cela ne fonctionne pas. Si je fais ça:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @staticmethod    
    def my_function(): pass

Je reçois une exception *, et si je fais cela:

class C(object):
    __metaclass__ = abc.ABCMeta

    @staticmethod    
    @abc.abstractmethod
    def my_function(): pass

La méthode abstraite n'est pas appliquée.

Comment créer une méthode statique abstraite?

*L'éxéption:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
79
Ram Rachum
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
31
Rosh Oxymoron

En commençant par Python 3.3 , c'est possible de combiner@staticmethod et @abstractmethod, donc aucune des autres suggestions n'est plus nécessaire:

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

Cela le fera:

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

Vous allez "Eh? Il renomme simplement @abstractmethod", et c'est tout à fait correct. Parce que toute sous-classe de ce qui précède devra de toute façon inclure le décorateur @staticmethod. Vous n'en avez pas besoin ici, sauf comme documentation lors de la lecture du code. Une sous-classe devrait ressembler à ceci:

  >>> class B(A):
  ...     @staticmethod
  ...     def themethod():
  ...         print "Do whatevs"

Pour avoir une fonction qui vous obligerait à faire de cette méthode une méthode statique, vous devez sous-classer ABCmeta pour vérifier cela et l'appliquer. C'est beaucoup de travail sans réel retour. (Si quelqu'un oublie le décorateur @staticmethod, il obtiendra une erreur claire de toute façon, cela ne mentionnera tout simplement pas les méthodes statiques.

Donc, en fait, cela fonctionne aussi bien:

  >>> import abc
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abc.abstractmethod
  ...     def themethod():
  ...         """Subclasses must implement this as a @staticmethod"""
  ...          pass

Mise à jour - Une autre façon de l'expliquer:

Qu'une méthode soit statique contrôle comment elle est appelée. Une méthode abstraite n'est jamais appelée. Et la méthode statique abstraite est donc un concept assez inutile, sauf à des fins de documentation.

12
Lennart Regebro

Ce n'est actuellement pas possible dans Python 2.X, qui imposera uniquement que la méthode soit abstraite ou statique, mais pas les deux.

Dans Python 3.2+, les nouveaux décorateursabc.abstractclassmethod et abc.abstractstaticmethod ont été ajoutés pour combiner leur application de l'abstrait et de la statique ou de l'abstrait et une méthode de classe.

Voir Problème Python 5867

4
Nick