在我的 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 3.3 开始,可以组合
@staticmethod
和 @abstractmethod
,因此不再需要其他建议:
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
自 3.3 版以来
@abstractstaticmethod
已被弃用(但在 Python 3.13 中仍然存在)。
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
>>> 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
更新 - 另一种解释方式:
方法是静态的,它控制着它的调用方式。 抽象方法永远不会被调用。 因此,除了用于文档目的之外,抽象静态方法是一个毫无意义的概念。
文档如下所述:
当所以,
abstractmethod()
与其他方法结合使用时 描述符,它应该作为最里面的装饰器应用,...
@abstractmethod
一定是最里面的装饰器,如下所示:
from abc import ABC, abstractmethod
class Person(ABC):
@classmethod
@abstractmethod # The innermost decorator
def test1(cls):
pass
@staticmethod
@abstractmethod # The innermost decorator
def test2():
pass
@property
@abstractmethod # The innermost decorator
def name(self):
pass
@name.setter
@abstractmethod # The innermost decorator
def name(self, name):
pass
@name.deleter
@abstractmethod # The innermost decorator
def name(self):
pass
然后,您需要在子类中重写它们,如下所示:
class Student(Person):
def __init__(self, name):
self._name = name
@classmethod
def test1(cls): # Overrides abstract class method
print("Test1")
@staticmethod
def test2(): # Overrides abstract static method
print("Test2")
@property
def name(self): # Overrides abstract getter
return self._name
@name.setter
def name(self, name): # Overrides abstract setter
self._name = name
@name.deleter
def name(self): # Overrides abstract deleter
del self._name
然后,您可以实例化子类并调用它们,如下所示:
obj = Student("John") # Instantiates "Student" class
obj.test1() # Class method
obj.test2() # Static method
print(obj.name) # Getter
obj.name = "Tom" # Setter
print(obj.name) # Getter
del obj.name # Deleter
print(hasattr(obj, "name"))
输出:
Test1
Test2
John
Tom
False
您可以查看我的回答,其中解释了抽象属性。