【问题标题】:`staticmethod` and `abc.abstractmethod`: Will it blend?`staticmethod` 和 `abc.abstractmethod`:会融合吗?
【发布时间】: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__'

【问题讨论】:

    标签: python abstract-class static-methods


    【解决方案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

      【讨论】:

      【解决方案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 没有添加任何解释
      猜你喜欢
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2013-01-18
      • 2010-12-14
      • 2014-07-15
      • 2011-07-13
      • 2012-04-16
      相关资源
      最近更新 更多