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

Posted

技术标签:

【中文标题】`staticmethod` 和 `abc.abstractmethod`:会融合吗?【英文标题】:`staticmethod` and `abc.abstractmethod`: Will it blend? 【发布时间】:2011-05-27 08:10:22 【问题描述】:

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

【问题讨论】:

【参考方案1】:

Python 3.3 开始,它是 possible to combine @staticmethod@abstractmethod,因此不再需要其他建议:

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

自version 3.3 以来,不推荐使用进一步的@abstractstatic

【讨论】:

注意你必须把@staticmethod放在第一位,否则你会得到AttributeError: attribute '__isabstractmethod__' of 'staticmethod' objects is not writable @property 相同 如果这是公认的答案,那将非常有帮助! 正是我想要的。谢谢! 是的,顺序很重要,如果你先写@abstractmethod,它就行不通了。【参考方案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

更新 - 另一种解释方式:

方法是静态的,控制它的调用方式。 永远不会调用抽象方法。 因此,抽象静态方法是一个毫无意义的概念,除非用于文档目的。

【讨论】:

【参考方案3】:

这在 Python 2.X 中目前是不可能的,它只会强制方法是抽象的或静态的,而不是两者。

在 Python 3.2+ 中,添加了新的装饰器abc.abstractclassmethodabc.abstractstaticmethod 以将它们强制执行为抽象和静态或抽象和类方法。

见Python Issue 5867

【讨论】:

虽然在 Python 3.2 中是新的,但 abstractclassmethodabstractstaticmethod 在 Python 3.3 以及 abstractproperty 中很快被弃用。 docs.python.org/3/library/abc.html 仅供参考:bugs.python.org/issue11610 描述了贬值,以及实现它的新方法......【参考方案4】:
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

【讨论】:

打得好,先生或女士 :-) 您在顶部漏掉了import abc;以及显示 A 实例化的子类。(例如,class B(A):\n @staticmethod\n def test():\n print 10\n 我更新了代码以与子类化一起正常工作。 A.test 也应该有__isabstractmethod__ 属性。 是否应该将abstractstatic 添加到abc.py 的上游? abstractstaticmethod 自 3.3 版起已弃用:现在可以将 staticmethod 与 abstractmethod() 一起使用,从而使此装饰器变得多余。 link 抱歉 -1 没有添加任何解释

以上是关于`staticmethod` 和 `abc.abstractmethod`:会融合吗?的主要内容,如果未能解决你的问题,请参考以下文章

@staticmethod 和 @property

当我需要在 python 编程中使用@staticmethod 和@classmethod 时? [复制]

类的静态方法@staticmethod

@classmethod和@staticmethod

@staticmethod和@classmethod的作用与区别

python--staticmethod(静态方法)和classmethod(类方法)