`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
那么抽象方法就没有被强制执行。
我该如何创建一个抽象的静态方法呢?
*异常信息:
File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'
5 个回答
这样做就可以了:
>>> 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
更新 - 另一种解释方式:
一个方法是静态的,这决定了它是如何被调用的。抽象方法是永远不会被调用的。因此,抽象静态方法其实是个没什么意义的概念,除了作为文档说明。
在编程中,有时候我们会遇到一些问题,比如代码运行不正常或者出现错误。这种时候,我们可以去一些技术论坛,比如StackOverflow,去寻找解决办法。在这些论坛上,很多人会分享他们的经验和解决方案,帮助其他人解决类似的问题。
当你在这些论坛上提问时,记得把你的问题描述清楚,包括你遇到的错误信息和你已经尝试过的解决办法。这样,其他人才能更好地理解你的问题,并给出有效的建议。
同时,也要注意查看别人提问的方式,学习如何更好地表达自己的问题,这样能提高你获得帮助的机会。
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
从Python 3.3开始,可以把@staticmethod
和@abstractmethod
结合使用,所以之前提到的其他建议就不需要了:
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
另外,@abstractstatic
从3.3版本开始就不再推荐使用了。