# class – Is it possible to make abstract classes in Python?

## The Question :

362 people think this question is useful

How can I make a class or method abstract in Python?

I tried redefining __new__() like so:

class F:
def __new__(cls):
raise Exception("Unable to create an instance of abstract class %s" %cls)



but now if I create a class G that inherits from F like so:

class G(F):
pass



then I can’t instantiate G either, since it calls its super class’s __new__ method.

Is there a better way to define an abstract class?

The Question Comments :

## The Answer 1

624 people think this answer is useful

Use the abc module to create abstract classes. Use the abstractmethod decorator to declare a method abstract, and declare a class abstract using one of three ways, depending upon your Python version.

In Python 3.4 and above, you can inherit from ABC. In earlier versions of Python, you need to specify your class’s metaclass as ABCMeta. Specifying the metaclass has different syntax in Python 3 and Python 2. The three possibilities are shown below:

# Python 3.4+
from abc import ABC, abstractmethod
class Abstract(ABC):
@abstractmethod
def foo(self):
pass


# Python 3.0+
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
@abstractmethod
def foo(self):
pass


# Python 2
from abc import ABCMeta, abstractmethod
class Abstract:
__metaclass__ = ABCMeta

@abstractmethod
def foo(self):
pass



Whichever way you use, you won’t be able to instantiate an abstract class that has abstract methods, but will be able to instantiate a subclass that provides concrete definitions of those methods:

>>> Abstract()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstract with abstract methods foo
>>> class StillAbstract(Abstract):
...     pass
...
>>> StillAbstract()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class StillAbstract with abstract methods foo
>>> class Concrete(Abstract):
...     def foo(self):
...         print('Hello, World')
...
>>> Concrete()
<__main__.Concrete object at 0x7fc935d28898>



## The Answer 2

123 people think this answer is useful

The old-school (pre-PEP 3119) way to do this is just to raise NotImplementedError in the abstract class when an abstract method is called.

class Abstract(object):
def foo(self):
raise NotImplementedError('subclasses must override foo()!')

class Derived(Abstract):
def foo(self):
print 'Hooray!'

>>> d = Derived()
>>> d.foo()
Hooray!
>>> a = Abstract()
>>> a.foo()
Traceback (most recent call last): [...]



This doesn’t have the same nice properties as using the abc module does. You can still instantiate the abstract base class itself, and you won’t find your mistake until you call the abstract method at runtime.

But if you’re dealing with a small set of simple classes, maybe with just a few abstract methods, this approach is a little easier than trying to wade through the abc documentation.

## The Answer 3

20 people think this answer is useful

Here’s a very easy way without having to deal with the ABC module.

In the __init__ method of the class that you want to be an abstract class, you can check the “type” of self. If the type of self is the base class, then the caller is trying to instantiate the base class, so raise an exception. Here’s a simple example:

class Base():
def __init__(self):
if type(self) is Base:
raise Exception('Base is an abstract class and cannot be instantiated directly')
# Any initialization code
print('In the __init__  method of the Base class')

class Sub(Base):
def __init__(self):
print('In the __init__ method of the Sub class before calling __init__ of the Base class')
super().__init__()
print('In the __init__ method of the Sub class after calling __init__ of the Base class')

subObj = Sub()
baseObj = Base()



When run, it produces:

In the __init__ method of the Sub class before calling __init__ of the Base class
In the __init__  method of the Base class
In the __init__ method of the Sub class after calling __init__ of the Base class
Traceback (most recent call last):
File "/Users/irvkalb/Desktop/Demo files/Abstract.py", line 16, in <module>
baseObj = Base()
File "/Users/irvkalb/Desktop/Demo files/Abstract.py", line 4, in __init__
raise Exception('Base is an abstract class and cannot be instantiated directly')
Exception: Base is an abstract class and cannot be instantiated directly



This shows that you can instantiate a subclass that inherits from a base class, but you cannot instantiate the base class directly.

## The Answer 4

15 people think this answer is useful

Most Previous answers were correct but here is the answer and example for Python 3.7. Yes, you can create an abstract class and method. Just as a reminder sometimes a class should define a method which logically belongs to a class, but that class cannot specify how to implement the method. For example, in the below Parents and Babies classes they both eat but the implementation will be different for each because babies and parents eat a different kind of food and the number of times they eat is different. So, eat method subclasses overrides AbstractClass.eat.

from abc import ABC, abstractmethod

class AbstractClass(ABC):

def __init__(self, value):
self.value = value
super().__init__()

@abstractmethod
def eat(self):
pass

class Parents(AbstractClass):
def eat(self):
return "eat solid food "+ str(self.value) + " times each day"

class Babies(AbstractClass):
def eat(self):
return "Milk only "+ str(self.value) + " times or more each day"

food = 3
mom = Parents(food)
print("moms ----------")
print(mom.eat())

infant = Babies(food)
print("infants ----------")
print(infant.eat())



OUTPUT:

moms ----------
eat solid food 3 times each day
infants ----------
Milk only 3 times or more each day



## The Answer 5

9 people think this answer is useful

This one will be working in python 3

from abc import ABCMeta, abstractmethod

class Abstract(metaclass=ABCMeta):

@abstractmethod
def foo(self):
pass

Abstract()
>>> TypeError: Can not instantiate abstract class Abstract with abstract methods foo



## The Answer 6

7 people think this answer is useful

As explained in the other answers, yes you can use abstract classes in Python using the abc module. Below I give an actual example using abstract @classmethod, @property and @abstractmethod (using Python 3.6+). For me it is usually easier to start off with examples I can easily copy&paste; I hope this answer is also useful for others.

Let’s first create a base class called Base:

from abc import ABC, abstractmethod

class Base(ABC):

@classmethod
@abstractmethod
def from_dict(cls, d):
pass

@property
@abstractmethod
def prop1(self):
pass

@property
@abstractmethod
def prop2(self):
pass

@prop2.setter
@abstractmethod
def prop2(self, val):
pass

@abstractmethod
def do_stuff(self):
pass



Our Base class will always have a from_dict classmethod, a property prop1 (which is read-only) and a property prop2 (which can also be set) as well as a function called do_stuff. Whatever class is now built based on Base will have to implement all of these four methods/properties. Please note that for a method to be abstract, two decorators are required – classmethod and abstract property.

Now we could create a class A like this:

class A(Base):
def __init__(self, name, val1, val2):
self.name = name
self.__val1 = val1
self._val2 = val2

@classmethod
def from_dict(cls, d):
name = d['name']
val1 = d['val1']
val2 = d['val2']

return cls(name, val1, val2)

@property
def prop1(self):
return self.__val1

@property
def prop2(self):
return self._val2

@prop2.setter
def prop2(self, value):
self._val2 = value

def do_stuff(self):
print('juhu!')

def i_am_not_abstract(self):
print('I can be customized')



All required methods/properties are implemented and we can – of course – also add additional functions that are not part of Base (here: i_am_not_abstract).

Now we can do:

a1 = A('dummy', 10, 'stuff')
a2 = A.from_dict({'name': 'from_d', 'val1': 20, 'val2': 'stuff'})

a1.prop1
# prints 10

a1.prop2
# prints 'stuff'



As desired, we cannot set prop1:

a.prop1 = 100



will return

AttributeError: can’t set attribute

Also our from_dict method works fine:

a2.prop1
# prints 20



If we now defined a second class B like this:

class B(Base):
def __init__(self, name):
self.name = name

@property
def prop1(self):
return self.name



and tried to instantiate an object like this:

b = B('iwillfail')



we will get an error

TypeError: Can’t instantiate abstract class B with abstract methods do_stuff, from_dict, prop2

listing all the things defined in Base which we did not implement in B.

## The Answer 7

3 people think this answer is useful

You can also harness the __new__ method to your advantage. You just forgot something. The __new__ method always returns the new object so you must return its superclass’ new method. Do as follows.

class F:
def __new__(cls):
if cls is F:
raise TypeError("Cannot create an instance of abstract class '{}'".format(cls.__name__))
return super().__new__(cls)



When using the new method, you have to return the object, not the None keyword. That’s all you missed.

## The Answer 8

3 people think this answer is useful

I find the accepted answer, and all the others strange, since they pass self to an abstract class. An abstract class is not instantiated so can’t have a self.

So try this, it works.

from abc import ABCMeta, abstractmethod

class Abstract(metaclass=ABCMeta):
@staticmethod
@abstractmethod
def foo():
"""An abstract method. No need to write pass"""

class Derived(Abstract):
def foo(self):
print('Hooray!')

FOO = Derived()
FOO.foo()



## The Answer 9

3 people think this answer is useful
 from abc import ABCMeta, abstractmethod

#Abstract class and abstract method declaration
class Jungle(metaclass=ABCMeta):
#constructor with default values
def __init__(self, name="Unknown"):
self.visitorName = name

def welcomeMessage(self):
print("Hello %s , Welcome to the Jungle" % self.visitorName)

# abstract method is compulsory to defined in child-class
@abstractmethod
def scarySound(self):
pass



## The Answer 10

2 people think this answer is useful

also this works and is simple:

class A_abstract(object):

def __init__(self):
# quite simple, old-school way.
if self.__class__.__name__ == "A_abstract":
raise NotImplementedError("You can't instantiate this abstract class. Derive it, please.")

class B(A_abstract):

pass

b = B()

# here an exception is raised:
a = A_abstract()



## The Answer 11

-3 people think this answer is useful

In your code snippet, you could also resolve this by providing an implementation for the __new__ method in the subclass, likewise:

def G(F):
def __new__(cls):
# do something here



But this is a hack and I advise you against it, unless you know what you are doing. For nearly all cases I advise you to use the abc module, that others before me have suggested.

Also when you create a new (base) class, make it subclass object, like this: class MyBaseClass(object):. I don’t know if it is that much significant anymore, but it helps retain style consistency on your code

## The Answer 12

-4 people think this answer is useful

Just a quick addition to @TimGilbert’s old-school answer…you can make your abstract base class’s init() method throw an exception and that would prevent it from being instantiated, no?

>>> class Abstract(object):
...     def __init__(self):
...         raise NotImplementedError("You can't instantiate this class!")
...
>>> a = Abstract()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __init__
NotImplementedError: You can't instantiate this class!