Can't instantiate abstract class with abstract methods
Question:
I’m working on a kind of lib, and I’m getting an error.
Sorry couldn’t just copy and paste it
I went on the basis that the code below works.
test.py:
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class Base(object):
@abc.abstractmethod
def whatever(self,):
raise NotImplementedError
class SubClass(Base):
def __init__(self,):
super(Base, self).__init__()
self.whatever()
def whatever(self,):
print("whatever")
In the python shell:
>>> from test import *
>>> s = SubClass()
whatever
For my roster module, why am I getting this error:
Can't instantiate abstract class Player with abstract methods _Base__json_builder, _Base__xml_builder
Answers:
Your issue comes because you have defined the abstract methods in your base abstract class with __
(double underscore) prepended. This causes python to do name mangling at the time of definition of the classes.
The names of the function change from __json_builder
to _Base__json_builder
or __xml_builder
to _Base__xml_builder
. And this is the name you have to implement/overwrite in your subclass.
To show this behavior in your example –
>>> import abc
>>> import six
>>> @six.add_metaclass(abc.ABCMeta)
... class Base(object):
... @abc.abstractmethod
... def __whatever(self):
... raise NotImplementedError
...
>>> class SubClass(Base):
... def __init__(self):
... super(Base, self).__init__()
... self.__whatever()
... def __whatever(self):
... print("whatever")
...
>>> a = SubClass()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class SubClass with abstract methods _Base__whatever
When I change the implementation to the following, it works
>>> class SubClass(Base):
... def __init__(self):
... super(Base, self).__init__()
... self._Base__whatever()
... def _Base__whatever(self):
... print("whatever")
...
>>> a = SubClass()
whatever
But this is very tedious , you may want to think about if you really want to define your functions with __
(double underscore) . You can read more about name mangling here .
Easiest way to make it behave like it did in Python 2 is to use
exec('print("your code")', globals())
This will allow your code to access imports, classes and functions defined in the code will work correctly, etc.
This should only be done w/ code you trust.
I got the same error below:
TypeError: Can’t instantiate abstract class Animal with abstract methods sound
When I tried to instantiate Animal
abstract class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!")
obj = Animal() # Here
obj.sound()
And also, I got the same error below:
TypeError: Can’t instantiate abstract class Cat with abstract methods sound
When I didn’t override sound()
abstract method in Cat
class, then I instantiated Cat
class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!")
class Cat(Animal):
pass # I didn't override "sound()" abstract method
obj = Cat() # Here
obj.sound()
So, I overrided sound()
abstract method in Cat
class, then I instantiated Cat
class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!")
# I overrided "sound()" abstract method
class Cat(Animal):
def sound(self):
print("Meow!!")
obj = Cat() # Here
obj.sound()
Then, I could solve the error:
Meow!!
The error text is a bit inaccurate.
To be precise, you did not override the method of the parent class,
because private methods and attributes cannot be inherited,
which means they cannot be overridden.
But you can override protected methods (protected method should start with single underscore ‘_’).
I’m working on a kind of lib, and I’m getting an error.
Sorry couldn’t just copy and paste it
I went on the basis that the code below works.
test.py:
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class Base(object):
@abc.abstractmethod
def whatever(self,):
raise NotImplementedError
class SubClass(Base):
def __init__(self,):
super(Base, self).__init__()
self.whatever()
def whatever(self,):
print("whatever")
In the python shell:
>>> from test import *
>>> s = SubClass()
whatever
For my roster module, why am I getting this error:
Can't instantiate abstract class Player with abstract methods _Base__json_builder, _Base__xml_builder
Your issue comes because you have defined the abstract methods in your base abstract class with __
(double underscore) prepended. This causes python to do name mangling at the time of definition of the classes.
The names of the function change from __json_builder
to _Base__json_builder
or __xml_builder
to _Base__xml_builder
. And this is the name you have to implement/overwrite in your subclass.
To show this behavior in your example –
>>> import abc
>>> import six
>>> @six.add_metaclass(abc.ABCMeta)
... class Base(object):
... @abc.abstractmethod
... def __whatever(self):
... raise NotImplementedError
...
>>> class SubClass(Base):
... def __init__(self):
... super(Base, self).__init__()
... self.__whatever()
... def __whatever(self):
... print("whatever")
...
>>> a = SubClass()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class SubClass with abstract methods _Base__whatever
When I change the implementation to the following, it works
>>> class SubClass(Base):
... def __init__(self):
... super(Base, self).__init__()
... self._Base__whatever()
... def _Base__whatever(self):
... print("whatever")
...
>>> a = SubClass()
whatever
But this is very tedious , you may want to think about if you really want to define your functions with __
(double underscore) . You can read more about name mangling here .
Easiest way to make it behave like it did in Python 2 is to use
exec('print("your code")', globals())
This will allow your code to access imports, classes and functions defined in the code will work correctly, etc.
This should only be done w/ code you trust.
I got the same error below:
TypeError: Can’t instantiate abstract class Animal with abstract methods sound
When I tried to instantiate Animal
abstract class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!")
obj = Animal() # Here
obj.sound()
And also, I got the same error below:
TypeError: Can’t instantiate abstract class Cat with abstract methods sound
When I didn’t override sound()
abstract method in Cat
class, then I instantiated Cat
class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!")
class Cat(Animal):
pass # I didn't override "sound()" abstract method
obj = Cat() # Here
obj.sound()
So, I overrided sound()
abstract method in Cat
class, then I instantiated Cat
class as shown below:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def sound(self):
print("Wow!!")
# I overrided "sound()" abstract method
class Cat(Animal):
def sound(self):
print("Meow!!")
obj = Cat() # Here
obj.sound()
Then, I could solve the error:
Meow!!
The error text is a bit inaccurate.
To be precise, you did not override the method of the parent class,
because private methods and attributes cannot be inherited,
which means they cannot be overridden.
But you can override protected methods (protected method should start with single underscore ‘_’).