`staticmethod`と` abc.abstractmethod`:ブレンドされますか?


106

私のPythonアプリでは、staticmethodとの両方であるメソッドを作成したいと思い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
受け入れた回答を更新してください。
ニールG

回答:


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はトップから外れました。また、Aのインスタンス化を示すサブクラス(例:class B(A):\n @staticmethod\n def test():\n print 10\n
Dan Breslau

1
サブクラス化で適切に動作するようにコードを更新しました。A.testにも__isabstractmethod__属性が必要です。
Rosh Oxymoron、

3
abstractstatic上流に追加する必要がありabc.pyますか?
nnyby

3
abstractstaticmethodバージョン3.3で廃止:abstractmethod()でstaticmethodを使用できるようになり、このデコレーターが冗長になりました。リンク
irakli khitarishvili 2015

1
@iraklikhitarishviliそれでも、サブクラスのメソッドが静的であることは強制されません!staticmethodデコレータを複製する必要があります...それを回避する方法はありませんか?
étale-コホモロジー

199

以降ではPython 3.3組み合わせることも可能 @staticmethod@abstractmethodするので、他の提案はいずれも、もはや必要ありません。

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

32
@staticmethod最初に置く必要があることに注意してください。そうしないと、次のようになりますAttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Marco Sulla

3
以下のための同じ@property
zezollo

11
これが受け入れられた答えであるなら、それは本当に役に立ちます!
Keerthana Prabhakaran、2018

まさに私が探していたもの。ありがとう!
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

あなたは「え?それは@abstractmethodの名前を変更するだけです」と行き、これは完全に正しいです。とにかく、上記のサブクラスには@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.abstractclassmethodabc.abstractstaticmethodが追加され、抽象と静的または抽象であるという強制とクラスメソッドを組み合わせるようになりました。

Python Issue 5867を参照してください


11
Python 3.2の新機能であり、Python 3.3 abstractclassmethodおよびabstractstaticmethodで急速に非推奨になりましたabstractpropertydocs.python.org/3/library/abc.html
glarrain

4
参考までにbugs.python.org/issue11610 は、剥奪とそれを行うための新しい方法を説明しています...
FlipMcF
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.