`staticmethod` en `abc.abstractmethod`: gaat het samensmelten?

In mijn Python-app wil ik een methode maken die zowel een staticmethodals een abc.abstractmethod. Hoe doe ik dit?

Ik heb geprobeerd beide decorateurs toe te passen, maar het werkt niet. Als ik dit doe:

import abc
class C(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    @staticmethod    
    def my_function(): pass

Ik krijg een uitzondering*, en als ik dit doe:

class C(object):
    __metaclass__ = abc.ABCMeta
    @staticmethod    
    @abc.abstractmethod
    def my_function(): pass

De abstracte methode wordt niet afgedwongen.

Hoe kan ik een abstracte statische methode maken?

*De uitzondering:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'

Antwoord 1, autoriteit 100%

Vanaf Python 3.3is het mogelijk om@staticmethoden @abstractmethodte combineren, zodat geen van de andere suggesties meer nodig is:

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

Verdere @abstractstaticis verouderd sinds versie 3.3.


Antwoord 2, autoriteit 13%

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

Antwoord 3, autoriteit 5%

Dit zal het doen:

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

Je zegt “Eh? Het hernoemt gewoon @abstractmethod”, en dit is helemaal correct. Omdat elke subklasse van het bovenstaande sowieso de @staticmethod-decorateur moet bevatten. Je hebt het hier niet nodig, behalve als documentatie bij het lezen van de code. Een subklasse zou er als volgt uit moeten zien:

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

Om een ​​functie te hebben die je zou dwingen om van deze methode een statische methode te maken, zou je ABCmeta moeten subclasseren om daarop te controleren en het af te dwingen. Dat is veel werk zonder echt rendement. (Als iemand de @staticmethod-decorateur vergeet, krijgen ze sowieso een duidelijke foutmelding, alleen worden statische methoden niet genoemd.

Dus in feite werkt dit net zo goed:

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

Update – Een andere manier om het uit te leggen:

Dat een methode statisch is, bepaalt hoe deze wordt aangeroepen.
Een abstracte methode wordt nooit aangeroepen.
En abstracte statische methode is daarom een vrij zinloos concept, behalve voor documentatiedoeleinden.


Antwoord 4

Dit is momenteel niet mogelijk in Python 2.X, waardoor de methode alleen abstract of statisch is, maar niet beide.

In Python 3.2+ zijn de nieuwe decorateursabc.abstractclassmethoden abc.abstractstaticmethodtoegevoegd om hun handhaving van abstract en statisch of abstract en een klassenmethode te combineren.

Zie Python-uitgave 5867

Other episodes