假设我像这样定义abstract base class:
from abc import abstractmethod, ABCMeta
class Quacker(object):
__metaclass__ = ABCMeta
@abstractmethod
def quack(self):
return "Quack!"
这可确保从Quacker
派生的任何类都必须实现quack
方法。但是,如果我定义以下内容:
class PoliteDuck(Quacker):
def quack(self, name):
return "Quack quack %s!" % name
d = PoliteDuck() # no error
我允许实例化该课程,因为我提供了quack
方法,但功能签名并不匹配。我可以看到这在某些情况下可能有用,但我有兴趣确保我可以肯定地调用抽象方法。如果函数签名不同,这可能会失败!
那么:我如何强制执行匹配的函数签名?如果签名不匹配,我希望在创建对象时出错,就像我没有定义一样它根本就没有。
我知道这不是惯用的,如果我想要这些类型的保证,Python就是错误的语言,但旁边的那个关键 - 有可能吗?
答案 0 :(得分:21)
这比你想象的要糟糕。抽象方法仅按名称进行跟踪,因此您甚至不必将quack
作为方法来实例化子类。
class SurrealDuck(Quacker):
quack = 3
d = SurrealDuck()
print d.quack # Shows 3
系统中没有任何内容强制quack
甚至是一个可调用的对象,更不用说其参数与抽象方法的原始对象相匹配的对象了。最好的情况是,您可以创建子类ABCMeta
并自己添加代码,以将子代码中的类型签名与父代中的原始代码进行比较,但这实现起来并不重要。
(目前,将某些内容标记为“abstract”实质上只是将名称添加到父级(Quacker.__abstractmethods__
)中的冻结集属性中。使类可实例化就像将此属性设置为空迭代一样简单,对测试很有用。)
答案 1 :(得分:6)
我建议你看看pylint。我通过它的静态分析运行了这段代码,在你定义quack()方法的行上,它报告了:
Argument number differs from overridden method (arguments-differ)