`staticmethod` e` abc.abstractmethod`: si fonderanno?


106

Nella mia app Python voglio creare un metodo che sia sia un staticmethodche un abc.abstractmethod. Come faccio a fare questo?

Ho provato ad applicare entrambi i decoratori, ma non funziona. Se lo faccio:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

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

Ottengo un'eccezione * e se lo faccio:

class C(object):
    __metaclass__ = abc.ABCMeta

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

Il metodo astratto non viene applicato.

Come posso creare un metodo statico astratto?

*L'eccezione:

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

5
Aggiorna la tua risposta accettata.
Neil G

Risposte:


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
Ben giocato, signore o signora :-) Hai lasciato fuori import abcin alto; così come una sottoclasse che mostra un'istanza di A. (ad esempio class B(A):\n @staticmethod\n def test():\n print 10\n)
Dan Breslau

1
Ho aggiornato il codice per funzionare correttamente con le sottoclassi. A.test dovrebbe anche avere l' __isabstractmethod__attributo.
Rosh Oxymoron

3
Dovrebbe abstractstaticessere aggiunto a monte abc.py?
nnyby

3
abstractstaticmethod Deprecato dalla versione 3.3: ora è possibile usare staticmethod con abstractmethod (), rendendo ridondante questo decorator. link
irakli khitarishvili

1
@iraklikhitarishvili Tuttavia, ciò non impone che il metodo della sottoclasse sia statico! Devi duplicare il decoratore metodo statico ... Non c'è modo di aggirarlo?
étale-cohomology

199

A partire da Python 3.3 , è possibile combinare @staticmethod e @abstractmethod, quindi nessuno degli altri suggerimenti è più necessario:

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

32
Nota che devi inserire @staticmethodper primo, o otterraiAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Marco Sulla

3
Lo stesso per@property
Zezollo il

11
Sarebbe davvero utile se questa fosse la risposta accettata!
Keerthana Prabhakaran

Esattamente quello che stavo cercando. Grazie!
shanu khera

13

Questo lo farà:

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

Vai "Eh? Rinomina solo @abstractmethod", e questo è completamente corretto. Perché qualsiasi sottoclasse di quanto sopra dovrà includere comunque il decoratore @staticmethod. Non ne hai bisogno qui, tranne come documentazione durante la lettura del codice. Una sottoclasse dovrebbe essere simile a questa:

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

Per avere una funzione che ti costringa a rendere questo metodo un metodo statico dovresti sottoclassare ABCmeta per verificarlo e applicarlo. È un sacco di lavoro senza un vero ritorno. (Se qualcuno dimentica il decoratore @staticmethod riceverà comunque un chiaro errore, semplicemente non menzionerà i metodi statici.

Quindi in effetti funziona altrettanto bene:

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

Aggiornamento - Un altro modo per spiegarlo:

Il fatto che un metodo sia statico controlla come viene chiamato. Un metodo astratto non viene mai chiamato. E il metodo statico astratto è quindi un concetto piuttosto inutile, tranne che per scopi di documentazione.


4

Questo non è attualmente possibile in Python 2.X, che imporrà solo che il metodo sia astratto o statico, ma non entrambi.

In Python 3.2+, i nuovi decoratori abc.abstractclassmethodeabc.abstractstaticmethod sono stati aggiunti per combinare la loro applicazione di essere astratti e statici o astratti e un metodo di classe.

Vedi Python Issue 5867


11
Anche se nuovo in Python 3.2, abstractclassmethode abstractstaticmethodsono stati rapidamente deprecati in Python 3.3, così come abstractproperty. docs.python.org/3/library/abc.html
glarrain

4
FYI: bugs.python.org/issue11610 descrive la deprivazione e un nuovo modo per farlo ...
FlipMcF
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.