Python 纯虚函数可能和/或值得吗?

2024-02-28

我可能有不同的心态,主要是一名 C++ 程序员。这个问题与 Python 中的 OOP 有关,更具体地说,与纯虚拟方法有关。所以采用我改编的代码这个问题 https://stackoverflow.com/questions/4714136/python-how-to-implement-virtual-methods我正在看这个基本样本。

class Animal():
    def speak(self):
        print("...")

class Cat(Animal):
    def speak(self):
        print("meow")

class Dog(Animal):
    def speak(self):
        print("woof")

my_pets = [Dog(), Cat(), Dog()]

for _pet in my_pets:
     _pet.speak()

所以你会看到它为不同的派生类调用了 talk 函数。现在我的问题是鸭子打字一切都很好,我想我已经掌握了。然而,在 Python 中追求更严格的 OOP 是错误的吗?所以我看了看抽象基类 https://docs.python.org/2/library/abc.html特别是抽象方法 https://docs.python.org/2/library/abc.html#abc.abstractmethod。对我来说,这似乎只是允许我用 super 调用基类方法。有什么方法/理由(在Python中)可以使speak()纯这样,在没有说话的情况下实现派生动物会引发错误吗?

我对这种追求的论点是,当编写您希望人们子类化的模块和框架时,这将为他们自我记录他们需要实现该功能的事实。一个可能非常糟糕的主意是这样的,让基类“pure”函数抛出异常。问题是这个错误是在运行时发现的!

class VirtualException(BaseException):
    def __init__(self, _type, _func):
        BaseException(self)

class Animal():
    def speak(self):
        raise VirtualException()

class Cat(Animal):
    def speak(self):
        print("meow")

class Dog(Animal):
    def speak(self):
        print("woof")

class Wildebeest(Animal):
    def function2(self):
        print("What!")

my_pets = [Dog(), Cat(), Dog(), Wildebeest()]

for _pet in my_pets:
    _pet.speak()

抽象基类已经做了你想要的事情。abstractmethod与让您调用该方法无关super;无论如何你都可以这样做。相反,任何用以下修饰的方法abstractmethod必须重写子类才能实例化:

Python 3:

>>> class Foo(metaclass=abc.ABCMeta):
...     @abc.abstractmethod
...     def foo(self):
...         pass
...
>>> class Bar(Foo):
...     pass
...
>>> class Baz(Bar):
...     def foo(self):
...         return super(Baz, self).foo()
...
>>> Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Foo with abstract methods foo
>>> Bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Bar with abstract methods foo
>>> Baz()
<__main__.Baz object at 0x00000210D702E2B0>

Python 2:

>>> class Foo(object):
...     __metaclass__ = abc.ABCMeta
...     @abc.abstractmethod
...     def foo(self): pass
...
>>> class Bar(Foo): pass
...
>>> class Baz(Bar):
...     def foo(self): return super(Baz, self).foo()
...
>>> Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Foo with abstract methods foo
>>> Bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Bar with abstract methods foo
>>> Baz()
<__main__.Baz object at 0x0000000001EC10B8>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 纯虚函数可能和/或值得吗? 的相关文章

随机推荐