抽象类能否强制继承类实现一个静态方法?

9

如果有关系,Python 3.2...

以下代码显示“具体类”可以将some_method实现为静态方法或实例方法:

import abc

class SomeAbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def some_method(self): pass

class ValidConcreteClass1(SomeAbstractClass):

    @staticmethod
    def some_method():
        print("foo!")

class ValidConcreteClass2(SomeAbstractClass):

    def some_method(self):
        print("foo!")

ValidConcreteClass1.some_method()

instance = ValidConcreteClass2()
instance.some_method()

我的问题是,我能强制实现继承类中的some_method方法为静态吗?我注意到了@abc.abstractstaticmethod,但以下代码仍然可以正常运行。我认为它会拒绝ValidConreteClass2,因为some_method不是静态的:
import abc

class SomeAbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractstaticmethod
    def some_method(self): pass

class ValidConcreteClass1(SomeAbstractClass):

    @staticmethod
    def some_method():
        print("foo!")

class ValidConcreteClass2(SomeAbstractClass):

    def some_method(self):
        print("foo!")

ValidConcreteClass1.some_method()

instance = ValidConcreteClass2()
instance.some_method()
1个回答

2

我认为需要做一些澄清:

首先,在Python中,每个方法都是虚拟的 - 真正的虚拟的;因此,一个方法是静态的还是绑定到类或实例,这是子类的问题,而不是父类的问题。你没有真正的理由想要阻止这种情况发生 - 你的目的是什么?

其次,抽象基类会在实例化时检查是否存在抽象方法 - 如果您尝试实例化一个仍具有任何抽象方法的类,则会引发错误。但是,抽象基类无法对从类本身调用的静态或类方法执行任何检查 - 没有对方法本身执行任何检查,只是在方法上设置了一个属性 - 当类被实例化时,ABCMeta才会执行脏工作。

第三,abstractstaticmethod的目的是允许抽象方法 - 因此必须以某种方式被子类覆盖 - 成为静态方法并从任何地方使用 - 再次强调,没有对方法本身执行任何检查,因此以下代码是完全合法的:

import abc

class SomeAbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractstaticmethod
    def some_method(): 
        return 123

class ValidConcreteClass1(SomeAbstractClass):

    def some_method(self):
        return 456

inst = ValidConcreteClass1()
print(inst.some_method())
print(SomeAbstractClass.some_method())

唯一需要使用abstractstaticmethod/abstractclassmethod的原因是以下代码无法正常工作,因为装饰方法缺少字典。
class NotWorking(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    @staticmethod
    def some_method(self):
        return "asd"

最后一点: 如果你真的想要的话,你可以通过扩展ABCMeta来添加这样的功能,但除非你告诉我为什么要这样做,否则我不会给你一个钩子来实现它 :-)


我的想法很简单,就是我动态地收集了所有从某个抽象基类派生的类(类似于插件架构,程序在运行时才访问插件类)。我希望能够依赖于插件子类都公开了特定的静态方法。我可以尝试进行静态调用,并在失败时抛出错误,但我认为使用抽象基类可以帮助我解决这个问题。 - Matthew Lund
你已经确认 @abc.abstractstaticmethod 对我没有帮助,这是有用的信息。我认为就像你所说的,要么我不能拥有这个保证,要么我必须扩展 ABCMeta,但我不想这样做。 - Matthew Lund
我希望能够依赖于插件子类都公开了特定的静态方法。这并不是Python风格的。如果代码的作者没有正确实现类,那不是你的问题。 - Falmarri
1
这个参数不是在暗示Python甚至不应该有抽象基类吗?Python有抽象基类这一事实表明,至少有些人希望能够“强制执行”(虽然轻微地)一个合同,以便一个类能够被加载。尽管如此,我承认我的背景是强类型语言,在那里接口占主导地位,我仍在学习Pythonic的做事方式。 - Matthew Lund
1
Matthew,抽象基类做了它所说的事情 - 除非你覆盖所有抽象方法,否则无法实例化它。但是静态方法是类的接口的一部分 - 在Python中可以在实例上调用静态方法只是一个细节,也可以是一个特性 - 但如果您想要一个抽象静态/类方法,则需要一个抽象基类元类 - Alan Franzoni
我只是在回应Falmarri的评论...我理解你(Alan)所说的关于abc如何工作的内容。 - Matthew Lund

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接