`staticmethod` dan` abc.abstractmethod`: Apakah akan berbaur?

106

Di aplikasi Python saya, saya ingin membuat metode a staticmethoddan abc.abstractmethod. Bagaimana saya melakukan ini?

Saya mencoba menerapkan kedua dekorator, tetapi tidak berhasil. Jika saya melakukan ini:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

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

Saya mendapatkan pengecualian *, dan jika saya melakukan ini:

class C(object):
    __metaclass__ = abc.ABCMeta

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

Metode abstrak tidak dipaksakan.

Bagaimana cara membuat metode statis abstrak?

* Pengecualian:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
Ram Rachum
sumber
5
Harap perbarui jawaban yang Anda terima.
Neil G

Jawaban:

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
Rosh Oxymoron
sumber
7
Bagus, Tuan atau Nyonya :-) Anda tertinggal import abcdi bagian atas; serta subclass yang menunjukkan instansiasi A. (misalnya, class B(A):\n @staticmethod\n def test():\n print 10\n)
Dan Breslau
1
Saya memperbarui kode agar berfungsi dengan baik dengan subclassing. A. test juga harus memiliki __isabstractmethod__atribut.
Rosh Oxymoron
3
Harus abstractstaticditambahkan ke hulu abc.py?
nnyby
3
abstractstaticmethod Tidak digunakan lagi sejak versi 3.3: Sekarang dimungkinkan untuk menggunakan metode statis dengan abstractmethod (), membuat dekorator ini berlebihan. tautan
irakli khitarishvili
1
@iraklikhitarishvili Namun, itu tidak memaksa metode subkelas menjadi statis! Anda harus menduplikasi dekorator metode statis ... Apakah tidak ada jalan lain?
étale-cohomology
199

Dimulai dengan Python 3.3 , dimungkinkan untuk menggabungkan @staticmethod dan @abstractmethod, jadi tidak ada lagi saran lain yang diperlukan:

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
gerrit
sumber
32
Perhatikan bahwa Anda harus menempatkan @staticmethodsebagai yang pertama, atau Anda akan mendapatkanAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Marco Sulla
3
Sama untuk@property
zezollo
11
Akan sangat membantu jika ini adalah jawaban yang diterima!
Keerthana Prabhakaran
Persis apa yang saya cari. Terima kasih!
shanu khera
13

Ini akan melakukannya:

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

Anda berkata "Eh? Ini hanya mengganti nama @abstractmethod", dan ini sepenuhnya benar. Karena setiap subclass di atas harus menyertakan dekorator @staticmethod. Anda tidak membutuhkannya di sini, kecuali sebagai dokumentasi saat membaca kode. Sebuah subclass harus terlihat seperti ini:

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

Untuk memiliki fungsi yang akan memaksa Anda untuk membuat metode ini sebagai metode statis, Anda harus subclass ABCmeta untuk memeriksanya dan menerapkannya. Itu banyak pekerjaan tanpa pengembalian nyata. (Jika seseorang lupa dekorator @staticmethod mereka akan mendapatkan kesalahan yang jelas, itu tidak akan menyebutkan metode statis.

Jadi sebenarnya ini bekerja dengan baik:

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

Perbarui - Cara lain untuk menjelaskannya:

Bahwa metode adalah kontrol statis bagaimana dipanggil. Metode abstrak tidak pernah dipanggil. Dan metode statis abstrak karena itu merupakan konsep yang tidak berguna, kecuali untuk tujuan dokumentasi.

Lennart Regebro
sumber
4

Ini saat ini tidak memungkinkan di Python 2.X, yang hanya akan memberlakukan metode menjadi abstrak atau statis, tetapi tidak keduanya.

Dalam Python 3.2+, dekorator baru abc.abstractclassmethoddan abc.abstractstaticmethodditambahkan untuk menggabungkan penegakannya menjadi abstrak dan statis atau abstrak dan metode kelas.

Lihat Masalah Python 5867

Nick
sumber
11
Meskipun baru di Python 3.2, abstractclassmethoddan abstractstaticmethoddengan cepat ditinggalkan di Python 3.3, juga abstractproperty. docs.python.org/3/library/abc.html
glarrain
4
FYI: bugs.python.org/issue11610 menjelaskan deprication, dan cara baru untuk melakukannya ...
FlipMcF