How to implement virtual methods in Python?

I know virtual methods from PHP or Java.

How can they be implemented in Python?

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

+54
python virtual-method
Jan 17 2018-11-17T00:
source share
7 answers

Of course, you don’t even need to define a method in the base class. In Python, methods are better than virtual - they are completely dynamic, because typing in Python is a duck.

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() 

Cat and Dog in Python do not even have to inherit a common base class to allow this behavior - you get it for free. However, some programmers prefer to define their class hierarchies in a more rigid way, in order to better document them and impose some typing rigor. It is also possible - see, for example, the standard abc module .

+81
Jan 17 2018-11-11T00:
source share

Python methods are always virtual.

+44
Jan 17 2018-11-17T00:
source share

raise NotImplementedError()

This is the recommended exception for "pure virtual methods" of "abstract" base classes that do not implement the method.

https://docs.python.org/3.5/library/exceptions.html#NotImplementedError says:

This exception comes from RuntimeError . In user-defined base classes, abstract methods should throw this exception when they need derived classes to override the method.

As others have said, this is basically a documentation agreement and is not required, but this way you get a more significant exception than a missing attribute error.

For example:

 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() 

gives:

 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 

Related: is it possible to make abstract classes in Python?

+22
Aug 02 '16 at 10:07 on
source share

In fact, in version 2.6, python provides something called abstract base classes, and you can explicitly set virtual methods, for example:

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

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

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

+18
Oct 11 '13 at
source share

Python methods are always virtual

as Ignacio said In some way, class inheritance might be the best approach to implementing 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 

The results should be:

 I am an unknown animal I am a dog named Rover Rover has 4 legs 
+8
Aug 22 '15 at 0:44
source share

Python methods are always virtual.

... if they are not private! Too bad for a C ++ guy.

+5
Jul 28 '17 at 7:08
source share

Something like a virtual method in C ++ (calling the implementation of a method of a derived class through a link or a pointer to a base class) does not make sense in Python, since Python has no typing. (Although I do not know how virtual methods work in Java and PHP.)

But if by “virtual” you mean calling the lowest implementation in the inheritance hierarchy, then this is what you always get in Python, as several answers indicate.

Well, almost always ...

As dplamp pointed out, not all methods in Python behave this way. Dander method does not. And I think this is not a very famous feature.

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

 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 changed was to make prop_a() more complicated method.

The problem with the first behavior may be that you cannot change the behavior of prop_a() in a derived class without affecting the behavior of prop_b() . This very good report by Raymond Hettinger provides an example for the case when it is inconvenient.

+1
Dec 29 '18 at 10:16
source share



All Articles