How to implement virtual methods in Python?
我知道PHP或Java的虚拟方法。
它们如何在Python中实现?
或者我必须在抽象类中定义一个空方法并重写它吗?
当然,您甚至不必在基类中定义方法。在python中,方法比虚拟方法更好——它们是完全动态的,因为在python中输入的是duck类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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() |
python中的
python方法总是虚拟的。
这是建议对不实现方法的"抽象"基类的"纯虚拟方法"引发的异常。
https://docs.python.org/3.5/library/exceptions.html notimplementederror说:
This exception is derived from
RuntimeError . In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method.
正如其他人所说,这主要是一种文档约定,不需要,但这样您得到的异常比缺少属性错误更有意义。
例如。:
1 2 3 4 5 6 7 8 9 10 11 12 | class Base(object): def virtualMethod(self): raise NotImplementedError() def usesVirtualMethod(self): return self.virtualMethod() + 1 class Derived(Base): def virtualMethod(self): return 1 print Derived().usesVirtualMethod() Base().usesVirtualMethod() |
给予:
1 2 3 4 5 6 7 8 9 | 2 Traceback (most recent call last): File"./a.py", line 13, in <module> Base().usesVirtualMethod() File"./a.py", line 6, in usesVirtualMethod return self.virtualMethod() + 1 File"./a.py", line 4, in virtualMethod raise NotImplementedError() NotImplementedError |
相关:是否可以在Python中创建抽象类?
实际上,在2.6版中,python提供了一种称为抽象基类的东西,您可以显式地设置如下虚拟方法:
1 2 3 4 5 6 7 | from abc import ABCMeta from abc import abstractmethod ... class C: __metaclass__ = ABCMeta @abstractmethod def my_abstract_method(self, ...): |
如果类不是从已经使用元类的类继承的,那么它工作得很好。
来源:http://docs.python.org/2/library/abc.html
Python methods are always virtual
就像伊格纳西奥说的不知何故,类继承可能是实现所需内容的更好方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 |
结果应该是:
1 2 3 | I am an unknown animal I am a dog named Rover Rover has 4 legs |
Python methods are always virtual.
…前提是他们不是私人的!对一个C++的家伙来说太糟糕了。
类似于C++中的虚拟方法(通过引用或指向基类的指针调用派生类的方法)在Python中没有意义,因为Python没有键入。(我不知道虚拟方法是如何在Java和PHP中工作的。)
但是,如果您所说的"虚拟"是指调用继承层次结构中最底层的实现,那么这就是您在Python中得到的,正如一些答案所指出的那样。
嗯,几乎总是……
正如dplamp所指出的,并非所有的Python方法都是这样。邓德方法没有。我认为这是一个不太知名的特性。
考虑这个人为的例子
1 2 3 4 5 6 7 8 9 | 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 |
现在
1 2 3 4 | >>> B().prop_b() 20 >>> A().prob_b() 10 |
但是,考虑一下这个
1 2 3 4 5 6 7 8 9 | 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 |
现在
1 2 3 4 | >>> B().prop_b() 10 >>> A().prob_b() 10 |
我们唯一改变的是使
第一个行为的一个问题是,在不影响