`staticmethod`和`abc.abstractmethod`:会融合吗?

问题:`staticmethod`和`abc.abstractmethod`:会融合吗?

在我的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

没有强制执行抽象方法。

如何制作抽象的静态方法?

*exceptions:

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

In my Python app I want to make a method that is both a staticmethod and an abc.abstractmethod. How do I do this?

I tried applying both decorators, but it doesn’t work. If I do this:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

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

I get an exception*, and if I do this:

class C(object):
    __metaclass__ = abc.ABCMeta

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

The abstract method is not enforced.

How can I make an abstract static method?

*The exception:

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

回答 0

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

回答 1

与开始的Python 3.3,它是可以组合 @staticmethod@abstractmethod,所以没有其他的建议是必要的了:

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

Starting with Python 3.3, it is possible to combine @staticmethod and @abstractmethod, so none of the other suggestions are necessary anymore:

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

回答 2

这样做:

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

更新-另一种解释方式:

方法是静态的,它控制着它的调用方式。从不调用抽象方法。因此,除了出于文档目的之外,抽象静态方法是一个毫无意义的概念。

This will do it:

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

You go “Eh? It just renames @abstractmethod”, and this is completely correct. Because any subclass of the above will have to include the @staticmethod decorator anyway. You have no need of it here, except as documentation when reading the code. A subclass would have to look like this:

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

To have a function that would enforce you to make this method a static method you would have to subclass ABCmeta to check for that and enforce it. That’s a lot of work for no real return. (If somebody forgets the @staticmethod decorator they will get a clear error anyway, it just won’t mention static methods.

So in fact this works just as well:

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

Update – Another way to explain it:

That a method is static controls how it is called. An abstract method is never called. And abstract static method is therefore a pretty pointless concept, except for documentation purposes.


回答 3

目前在Python 2.X中这是不可能的,Python 2.X仅将方法强制为抽象或静态方法,而不会两者都强制执行。

在Python 3.2+中,添加了新的装饰器abc.abstractclassmethodabc.abstractstaticmethod以将其强制实施抽象和静态或抽象与类方法结合起来。

参见Python Issue 5867

This is currently not possible in Python 2.X, which will only enforce the method to be abstract or static, but not both.

In Python 3.2+, the new decoratorsabc.abstractclassmethod and abc.abstractstaticmethod were added to combine their enforcement of being abstract and static or abstract and a class method.

See Python Issue 5867