Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Able to instantiate python class, in spite of it being Abstract (using abc)

This is in reference to the answer for this question to "Use abc module of python to create abstract classes." (by @alexvassel and accepted as an answer).

I tried the suggestions, but strangely enough, in spite of following the suggestions to use the abc way, it doesn't work for me. Hence I am posting it as a question here:

Here is my Python code:

from abc import ABCMeta, abstractmethod

class Abstract(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def foo(self):
        print("tst")

a = Abstract()
a.foo()

When I execute this module, here is the output on my console:

pydev debugger: starting (pid: 20388)
tst

as opposed to that accepted answer

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

So what am I doing right or wrong? Why does work and not fail? Appreciate any expert insight into this.

like image 952
jark Avatar asked Jun 15 '14 23:06

jark


People also ask

How do you instantiate an abstract class in Python?

Abstract classes cannot be instantiated, and require subclasses to provide implementations for the abstract methods.

Can an abstract class be instantiated?

Abstract classes have the following features: An abstract class cannot be instantiated. An abstract class may contain abstract methods and accessors.

What is ABC package in Python?

This module provides the infrastructure for defining abstract base classes (ABCs) in Python, as outlined in PEP 3119; see the PEP for why this was added to Python. (See also PEP 3141 and the numbers module regarding a type hierarchy for numbers based on ABCs.)

What is the difference between ABC and ABCMeta?

The only difference is that in the former case you need a simple inheritance and in the latter you need to specify the metaclass. From What's new in Python 3.4(emphasis mine): New class ABC has ABCMeta as its meta class. Using ABC as a base class has essentially the same effect as specifying metaclass=abc.


2 Answers

In Python 3 use the metaclass argument when creating the abstract base class:

from abc import ABCMeta, abstractmethod

class Abstract(metaclass=ABCMeta):

    @abstractmethod
    def foo(self):
        print("tst")

a = Abstract()
a.foo()
like image 72
Victory Avatar answered Oct 20 '22 06:10

Victory


In Python 2, you must assign the metaclass thusly:

import abc

class ABC(object):

    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def foo(self):
        return True

a = ABC()

Which raises a TypeError

Traceback (most recent call last):
  File "<pyshell#59>", line 1, in <module>
    a = ABC()
TypeError: Can't instantiate abstract class ABC with abstract methods foo

But in Python 3, assigning __metaclass__ as an attribute doesn't work (as you intend it, but the interpreter doesn't consider it an error, just a normal attribute as any other, which is why the above code would not raise an error). Metaclasses are now defined as a named argument to the class:

import abc

class ABC(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def foo(self):
        return True

a = ABC()

raises the TypeError:

Traceback (most recent call last):
  File "main.py", line 11, in 
    a = ABC()
TypeError: Can't instantiate abstract class ABC with abstract methods foo
like image 32
Russia Must Remove Putin Avatar answered Oct 20 '22 06:10

Russia Must Remove Putin