Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How define constructor implementation for an Abstract Class in Python?

I am trying to declare an abstract class A with a constructor with a default behavior: all subclasses must initialize a member self.n:

from abc import ABCMeta  class A(object):     __metaclass__ = ABCMeta      def __init__(self, n):         self.n = n 

However, I do not want to let the A class be instantiated because, well, it is an abstract class. The problem is, this is actually allowed:

a = A(3) 

This produces no errors, when I would expect it should.

So: how can I define an un-instantiable abstract class while defining a default behavior for the constructor?

like image 859
dabadaba Avatar asked Jun 28 '17 11:06

dabadaba


People also ask

Can we create constructor in abstract class in Python?

We are also adding an abstract constructor that can be called by its subclasses. To be fair I'm tempted to remove this constructor considering that an abstract class is not supposed to be instantiated. At the same time the constructor can be used as a guidance for the subclasses that will have to implement it.

Can abstract class implementation constructor?

Yes! Abstract classes can have constructors! Yes, when we define a class to be an Abstract Class it cannot be instantiated but that does not mean an Abstract class cannot have a constructor. Each abstract class must have a concrete subclass which will implement the abstract methods of that abstract class.

How do you declare and declare a constructor in an abstract class?

A constructor is used to initialize an object not to build the object. As we all know abstract classes also do have a constructor. So if we do not define any constructor inside the abstract class then JVM (Java Virtual Machine) will give a default constructor to the abstract class.

How do you call a constructor from an abstract class?

You can't call an abstract class constructor with a class instance creation expression, i.e. As constructors of abstract classes can only be called within subclass constructors (and by chaining one to another within the same class), I typically make them protected ... making them public would serve no purpose.


2 Answers

Making the __init__ an abstract method:

from abc import ABCMeta, abstractmethod  class A(object):     __metaclass__ = ABCMeta      @abstractmethod     def __init__(self, n):         self.n = n   if __name__ == '__main__':     a = A(3) 

helps:

TypeError: Can't instantiate abstract class A with abstract methods __init__ 

Python 3 version:

from abc import ABCMeta, abstractmethod  class A(object, metaclass=ABCMeta):      @abstractmethod     def __init__(self, n):         self.n = n   if __name__ == '__main__':     a = A(3) 

Works as well:

TypeError: Can't instantiate abstract class A with abstract methods __init__ 
like image 115
Mike Müller Avatar answered Oct 29 '22 00:10

Mike Müller


A not so elegant solution can be this:

class A(object):   def __init__(self, n):     if self.__class__ == A:       raise Exception('I am abstract!')     self.n = n 

Usage

class B(A):   pass a = A(1)  # Will throw exception b = B(1)  # Works fine as expected. 
like image 43
gipsy Avatar answered Oct 29 '22 01:10

gipsy