如何在 Python 中实现虚拟方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4714136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 17:09:30  来源:igfitidea点击:

How to implement virtual methods in Python?

pythonvirtual-functions

提问by Meloun

I know virtual methods from PHP or Java.

我知道来自 PHP 或 Java 的虚拟方法。

How can they be implemented in Python?

它们如何在 Python 中实现?

Or have I to define an empty method in an abstract class and override it?

还是我必须在抽象类中定义一个空方法并覆盖它?

采纳答案by Eli Bendersky

Sure, and you don't even have to define a method in the base class. In Python methods are better than virtual - they're completely dynamic, as the typing in Python is duck typing.

当然,您甚至不必在基类中定义方法。在 Python 中方法比虚拟更好 - 它们是完全动态的,因为 Python 中的类型是鸭子类型

class Dog:
  def say(self):
    print "hau"

class Cat:
  def say(self):
    print "meow"

pet = Dog()
pet.say() # prints "hau"
another_pet = Cat()
another_pet.say() # prints "meow"

my_pets = [pet, another_pet]
for a_pet in my_pets:
  a_pet.say()

Catand Dogin Python don't even have to derive from a common base class to allow this behavior - you gain it for free. That said, some programmers prefer to define their class hierarchies in a more rigid way to document it better and impose somestrictness of typing. This is also possible - see for example the abcstandard module.

Cat并且Dog在 Python 中甚至不必从公共基类派生来允许这种行为 - 您可以免费获得它。也就是说,一些程序员更喜欢以更严格的方式定义他们的类层次结构,以更好地记录它并强加一些严格的类型。这也是可能的——例如参见abc标准模块

回答by Ignacio Vazquez-Abrams

Python methods are always virtual.

Python 方法始终是虚拟的。

回答by user2795020

Actually, in version 2.6 python provides something called abstract base classesand you can explicitly set virtual methods like this:

实际上,在 2.6 版本中,python 提供了一些称为抽象基类的东西,您可以像这样显式设置虚拟方法:

from abc import ABCMeta
from abc import abstractmethod
...
class C:
    __metaclass__ = ABCMeta
    @abstractmethod
    def my_abstract_method(self, ...):

It works very well, provided the class does not inherit from classes that already use metaclasses.

它工作得很好,前提是该类不从已经使用元类的类继承。

source: http://docs.python.org/2/library/abc.html

来源:http: //docs.python.org/2/library/abc.html

回答by Jinzo

Python methods are always virtual

Python 方法总是虚拟的

like Ignacio said yet Somehow class inheritance may be a better approach to implement what you want.

就像伊格纳西奥说的,不知何故,类继承可能是实现你想要的更好的方法。

class Animal:
    def __init__(self,name,legs):
        self.name = name
        self.legs = legs

    def getLegs(self):
        return "{0} has {1} legs".format(self.name, self.legs)

    def says(self):
        return "I am an unknown animal"

class Dog(Animal): # <Dog inherits from Animal here (all methods as well)

    def says(self): # <Called instead of Animal says method
        return "I am a dog named {0}".format(self.name)

    def somethingOnlyADogCanDo(self):
        return "be loyal"

formless = Animal("Animal", 0)
rover = Dog("Rover", 4) #<calls initialization method from animal

print(formless.says()) # <calls animal say method

print(rover.says()) #<calls Dog says method
print(rover.getLegs()) #<calls getLegs method from animal class

Results should be:

结果应该是:

I am an unknown animal
I am a dog named Rover
Rover has 4 legs

回答by Konstantin

Something like a virtual method in C++ (calling method implementation of a derived class through a reference or pointer to the base class) doesn't make sense in Python, as Python doesn't have typing. (I don't know how virtual methods work in Java and PHP though.)

像 C++ 中的虚拟方法(通过引用或指向基类的指针调用派生类的方法实现)在 Python 中没有意义,因为 Python 没有类型。(虽然我不知道虚拟方法在 Java 和 PHP 中是如何工作的。)

But if by "virtual" you mean calling the bottom-most implementation in the inheritance hierarchy, then that's what you always get in Python, as several answers point out.

但是,如果“虚拟”是指调用继承层次结构中最底层的实现,那么正如几个答案所指出的那样,这就是您在 Python 中总是得到的。

Well, almost always...

嗯,几乎总是...

As dplamp pointed out, not all methods in Python behave like that. Dunder method don't. And I think that's a not so well known feature.

正如 dplamp 指出的那样,并非 Python 中的所有方法都具有这种行为。邓德方法不行。而且我认为这是一个不太知名的功能。

Consider this artificial example

考虑这个人为的例子

class A:
    def prop_a(self):
        return 1
    def prop_b(self):
        return 10 * self.prop_a()

class B(A):
    def prop_a(self):
        return 2

Now

现在

>>> B().prop_b()
20
>>> A().prob_b()
10

However, consider this one

然而,考虑这个

class A:
    def __prop_a(self):
        return 1
    def prop_b(self):
        return 10 * self.__prop_a()

class B(A):
    def __prop_a(self):
        return 2

Now

现在

>>> B().prop_b()
10
>>> A().prob_b()
10

The only thing we've changes was making prop_a()a dunder method.

我们唯一改变的是制作prop_a()一个dunder方法。

A problem with the first behavior can be that you can't change the behavior of prop_a()in the derived class without impacting the behavior of prop_b(). Thisvery nice talk by Raymond Hettinger gives an example for a use case where this is inconvenient.

第一个行为的问题可能是您无法prop_a()在不影响prop_b(). Raymond Hettinger 的这个非常好的演讲给出了一个不方便的用例示例。