Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I not restricted from instantiating abstract classes in Python 3.4?

I have written a Python script and just found out that Python 3.4 does not restrict an abstract class from being instantiated while Python 2.7.8 did.

Here is my abstract class in the file named Shape.py.

from abc import ABCMeta, abstractmethod

class Shape:

    __metaclass__ = ABCMeta # Making the class abstract

    def __init__(self):
        pass:

    @abstractmethod
    def getArea(self):
        print("You shouldn't have called me.")
        return None

Now I created another class that inherits from the abstract class Shape:
Filename: Circle.py

from Shape import Shape

class Circle(Shape):

    PI = 3.141

    def __init__(self, radius=0):
        self.radius = radius

    def getArea(self):    # Overriding it from Shape class
        return self.PI * self.radius ** 2

Now in my Main.py:

from Shape import Shape
from Circle import Circle

shape = Shape() # This gave me errors in Python 2.7.8 but not in Python 3.4
shape2 = Circle(5) 

print("Area of shape = "+str(shape.getArea()))    # This should have not been executed.
print("Area of circle = "+str(shape2.getArea()))

This Main.py gives errors on commented areas in Python2.7.8 but works fine on Python3.4.
Output on Python3.4:

You shouldn't have called me
Area of shape = None
Area of circle = 78.525
  1. Why is this happening? This is not what abstraction is! Is it?
  2. Or has there been any new way introduced for abstraction in Python 3.4?
  3. Can any one give me the link of official documentation for python 3.4?
like image 280
Aditya Singh Avatar asked Feb 12 '23 22:02

Aditya Singh


1 Answers

In Python 3, you declare a metaclass differently:

class Shape(metaclass=ABCMeta):

See the Customizing class creation documentation:

The class creation process can be customised by passing the metaclass keyword argument in the class definition line, or by inheriting from an existing class that included such an argument.

All examples in the abc module documentation for Python 3 also use the correct notation.

This was changed to give metaclasses a chance to get involved with class creation earlier than was possible in Python 2; see PEP 3115.

The __metaclass__ attribute has no special meaning anymore, so you didn't actually create a proper abstract class.

Demo with Python 3.4:

>>> from abc import ABCMeta, abstractmethod
>>> class Shape(metaclass=ABCMeta):
...     @abstractmethod
...     def getArea(self):
...         print("You shouldn't have called me.")
...         return None
... 
>>> Shape()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Shape with abstract methods getArea
like image 79
Martijn Pieters Avatar answered Feb 14 '23 12:02

Martijn Pieters