静态方法和抽象方法: 它会混合吗?

在我的 Python 应用程序中,我想创建一个同时是 staticmethodabc.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__'
51268 次浏览
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

你说“啊?”?它只是重新命名了这个“抽象方法”,这是完全正确的。因为上面的任何子类无论如何都必须包含@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

更新-另一种解释方式:

方法是静态的将控制如何调用它。 从不调用抽象方法。 因此,抽象静态方法是一个非常无意义的概念,除非是为了文档的目的。

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

在 Python 3.2 + 中,添加了新的 decorsabc.abstractclassmethodabc.abstractstaticmethod,将它们的抽象和静态或抽象实现与类方法结合起来。

参见 Python 第5867期

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

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

进一步的 @abstractstatic版本3.3之后被弃用。

文件 如下:

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

你可以看到解释 抽象属性我的回答