web-dev-qa-db-ja.com

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

私のPythonアプリでは、staticmethodabc.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__'
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

Python 3.3からは、 結合可能@staticmethodおよび@abstractmethodなので、他の提案はもう必要ありません。

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

これはそれを行います:

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

更新-それを説明する別の方法:

メソッドが静的であることは、その呼び出し方法を制御します。抽象メソッドが呼び出されることはありません。したがって、抽象静的メソッドは、文書化の目的を除いて、かなり無意味な概念です。

12
Lennart Regebro

これは現在、Python 2.Xでは不可能です。これは、メソッドを抽象的または静的にするだけで、両方ではありません。

Python 3.2+、新しいデコレータabc.abstractclassmethodおよびabc.abstractstaticmethodは、抽象と静的または抽象とクラスメソッドの強制を組み合わせるために追加されました。

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

4
Nick