`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

Answers:


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

1
我更新了代码以使其与子类一起正常工作。A.test还应该具有该__isabstractmethod__属性。
Rosh Oxymoron 2010年

3
应该abstractstatic添加到上游abc.py吗?
nnyby

3
abstractstaticmethod从版本3.3开始不推荐使用:现在可以将staticmethod与abstractmethod()结合使用,从而使此装饰器变得多余。链接
irakli khitarishvili

1
@iraklikhitarishvili仍然,这并不强制子类的方法是静态的!您必须复制staticmethod装饰器...没办法解决吗?
étale-上同调

198

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

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

31
请注意,您必须@staticmethod放在第一位,否则您会得到AttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable
Marco Sulla

3
同样适用@property
zezollo

11
如果这是公认的答案,那将非常有帮助!
Keerthana Prabhakaran

正是我想要的。谢谢!
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 2.X仅将方法强制为抽象或静态方法,而不会两者都强制执行。

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

参见Python Issue 5867


11
虽然在Python 3.2中是新功能,但在Python 3.3 abstractclassmethodabstractstaticmethod中迅速不推荐使用abstractpropertydocs.python.org/3/library/abc.html
glarrain

4
仅供参考:bugs.python.org/issue11610 描述了贬低以及新的实现方法...
FlipMcF 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.