10

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.

Community
  • 1
  • 1
jark
  • 305
  • 1
  • 3
  • 11

2 Answers2

8

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()
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
Victory
  • 5,811
  • 2
  • 26
  • 45
  • 1
    I see. That is great information to know. It works after I modified the definition as suggested. Thanks. – jark Jun 16 '14 at 00:52
  • 2
    It appears that you can instantiate and call methods on an abstract class if it doesn't have any @abstractmethod – Peter Nov 01 '18 at 21:46
6

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
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • Thanks for the detailed explanation on why it doesn't raise an error with Python 2. I wish it did, without silently working as I didn't intend it to :( – jark Jun 16 '14 at 00:54
  • @jark Interesting you chose Victory's code, as it is invalid for Python 3 and actually doesn't demonstrate what you were looking for. – Russia Must Remove Putin Jun 16 '14 at 01:03
  • Aaron Hall, thanks for your feedback. I accepted Victory's answer because that was the first one that came in and I read and tried and it worked as I expected it to. I am not sure why you are saying that it is "Invalid for Python 3"? If I compare the code you have posted in your solution to what Victory has posted, both use exactly the same logic. The only difference being you have used "import abc" (and in turn using abc.abstract method etc.) vs Victory using "from abc import ABCMeta, abstractmethod" and using abstractmethod etc. Nothing personal against you are for Victory, – jark Jun 16 '14 at 02:00
  • I appreciate your detailed answer. But again please let me know how I mis-understood the answer by Victory and why it won't work and I shall consider accepting yours. – jark Jun 16 '14 at 02:05
  • @jark what he has fails on `a = Abstract()` (as it should) and `a.foo()` is irrelevant, it's obvious he didn't test his code, he merely copied yours and altered it. Nevertheless, accept the answer you feel helps you most. – Russia Must Remove Putin Jun 16 '14 at 03:23