Python 强制执行抽象方法实现是非语法的吗?

Python 强制执行抽象方法实现是非语法的吗?,python,oop,Python,Oop,在设计类时,抽象方法非常有用。据我所知,Python没有强制执行继承类以实现抽象方法的机制。在我的代码中(参见下面的示例),我在基类中输入了一个失败的断言,如果没有实现,就会导致运行时错误。这是非音速的吗 class Dog(Animal): def speak(self): return "bark" class Animal(): def speak(self): assert(False) #abstract 好吧,如果您没有在基类中包含方法speak,并且碰巧使用

在设计类时,抽象方法非常有用。据我所知,Python没有强制执行继承类以实现抽象方法的机制。在我的代码中(参见下面的示例),我在基类中输入了一个失败的断言,如果没有实现,就会导致运行时错误。这是非音速的吗

class Dog(Animal):
  def speak(self):
   return "bark"

class Animal():
  def speak(self):
   assert(False) #abstract

好吧,如果您没有在基类中包含方法
speak
,并且碰巧使用了它,那么代码无论如何都会失败。问题是,它的可能性有多大,以及如何告诉用户(一个
NotImplementedError
可能比一个断言更适合这里)。

Python实际上有抽象类和抽象方法:

>>> import abc
>>> 
>>> class IFoo(object):
...     __metaclass__ = abc.ABCMeta
...     
...     @abc.abstractmethod
...     def foo(self):
...         pass
... 
>>> foo = IFoo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Cant instantiate abstract class IFoo with abstract methods foo
>>> class FooDerived(IFoo):
...     pass
... 
>>> foo = FooDerived()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Cant instantiate abstract class FooDerived with abstract methods foo
>>> class FooImplements(FooDerived):
...     def foo(self):
...         print "foo'ed"
... 
>>> foo = FooImplements()
>>> foo.foo()
foo'ed
>>> 
如果出于某种原因,您不能使用
@abstractmethod
,但仍希望获得该效果,则应提出
NotImplementedError
。您可能希望这样做,因为您确实需要该类的实例,其中一些可能不需要实现可选功能。您仍然应该考虑通过
super()
调用函数的可能性。第一个近似值可能是这样的

class Foo(object):
    def bar(self, baz):
        if self.bar.im_func == Foo.bar.im_func:
            raise NotImplementedError, "Subclasses must implement bar"

一般来说,python并不总是能够直接对代码实施限制,至少从面向对象的角度来看是如此(考虑抽象类、私有方法等等)。 要强制子类实现方法,您可能需要执行以下操作:

class Animal():
  def speak(self):
   raise NotImplementedError #abstract

class Dog(Animal):
  def speak(self):
   return "bark"

class MuteAnimal(Animal):
  pass

这并不意味着该方法将由子类实现,但它将在不执行Salk方法时简单地引发错误。

< P> ABC是C++的伪品,与鸭类型相反。如果类动物不定义
说话
,它会毫不费力地做你想做的事

>>> class Animal(object):
...     pass
... 
>>> class Dog(Animal):
...     def speak(self):
...             print "bark"
... 
>>> animal = Animal()
>>> dog = Dog()
>>> animal.speak()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Animal' object has no attribute 'speak'
>>> dog.speak()
bark
类动物(对象): ... 通过 ... >>>犬类(动物): ... def发言(自我): ... 打印“树皮” ... >>>动物 >>>狗 >>>动物说话 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 AttributeError:“Animal”对象没有属性“speak” >>>狗说话 树皮
C++和相关语言强制您创建ABC,因为ABC实际上是一个接口描述。Python避免编译器强制执行的接口声明,因为它们试图在代码中记录通过非语言手段更好地执行的契约。

“Python避免编译器强制执行的接口声明,因为它们试图在代码中记录通过非语言手段更好地执行的契约。”WTF?请澄清这句话,它可能会对其他人更有帮助。此外,如果你要求你的库的用户在类中实现一个混合的方法,ABC和/或抽象方法在duck类型世界中是完全有效的。如果它是正确的软件工程,谁会在乎它是“非语法化”还是与特定社区灌输的信仰背道而驰呢。看看下面这个家伙的答案,忽略这个家伙。
>>> class Animal(object):
...     pass
... 
>>> class Dog(Animal):
...     def speak(self):
...             print "bark"
... 
>>> animal = Animal()
>>> dog = Dog()
>>> animal.speak()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Animal' object has no attribute 'speak'
>>> dog.speak()
bark