293

I am having trouble in using inheritance with Python. While the concept seems too easy for me in Java yet up till now I have been unable to understand in Python which is surprising to me at least.

I have a prototype which follow:

class Shape():
   def __init__(self, shape_name):
       self.shape = shape_name

class Rectangle(Shape):
   def __init__(self, name):
       self.shape = name

In the above code how can I make an abstract method that would need to be implemented for all the subclasses?

one noa
  • 345
  • 1
  • 3
  • 10
  • 6
    Btw this really was an afterthought in python. abstract interfaces and such were just recently introduced. Since python isn't compiled, you should make your intent clear in documentation instead of abstract classes. – Falmarri Dec 08 '10 at 00:05
  • Also a *very* good application for unit testing. As Python is not compiled, I don't begin to trust code until I've unit tested it. – Technophile Jul 08 '21 at 15:05

6 Answers6

356

Before abc was introduced you would see this frequently.

class Base(object):
    def go(self):
        raise NotImplementedError("Please Implement this method")


class Specialized(Base):
    def go(self):
        print "Consider me implemented"
kevpie
  • 25,206
  • 2
  • 24
  • 28
  • 74
    this is more pythonic than the accepted answer in my opinion, since it follows the python adage "we're all adults here" - if a subclass doesn't implement this type of abstract method, it will have to deal with the consequences – Emmett Butler Sep 24 '12 at 15:17
  • 2
    @EmmettJ.Butler But abc should be implemented after all. Am I right? – Nabin May 24 '17 at 09:13
  • 2
    @Spiderman nope, abc is not for simple base classes, abc is when you need isinstance checks, similar to isinstance(x, number) or isinstance(x, collections.abc.Sequence). – Stan Prokop Jun 08 '17 at 18:28
  • 29
    @EmmettJ.Butler But it doesn't provide any immediate feedback. It provides the feedback only after the method was used, which makes this mechanism completely useless as an abstract class. – Błażej Michalik Jul 09 '18 at 10:53
323

Something along these lines, using ABC

import abc

class Shape(object):
    __metaclass__ = abc.ABCMeta
    
    @abc.abstractmethod
    def method_to_implement(self, input):
        """Method documentation"""
        return
    

Also read this good tutorial: https://pymotw.com/3/abc/

You can also check out zope.interface which was used prior to introduction of ABC in python.

frainfreeze
  • 567
  • 6
  • 20
pyfunc
  • 65,343
  • 15
  • 148
  • 136
  • Does adding this effects the other things as well ?? ie will other part of my class code need to be changed ?? –  Dec 08 '10 at 00:03
  • @user506710: Remember that it is only introduced now. Earlier, Python used "duck typing". – pyfunc Dec 08 '10 at 00:05
  • 2
    @user506710: The only other part of your code that might need to be changed is if you are already using a metaclass. In this case, just have your metaclass derive from `abc.ABCMeta` instead of from `type` and you should be OK. If you don't know what a metaclass is, don't worry about it. :-) – kindall Dec 08 '10 at 00:15
  • 1
    The linked tutorial is **much** clearer than the Python abc doc (http://docs.python.org/2/library/abc.html); yet they say the *same thing*. – Jacob Marble Feb 26 '13 at 05:02
  • 6
    This syntax doesn't work in python 3, see this question/answer: http://stackoverflow.com/a/18513858/1240268. – Andy Hayden Sep 13 '14 at 02:37
  • 2
    In python 3, you should use this answer instead. https://stackoverflow.com/a/13646263/5093308 – Zhou Hongbo Jun 23 '20 at 07:09
48

See the abc module. Basically, you define __metaclass__ = abc.ABCMeta on the class, then decorate each abstract method with @abc.abstractmethod. Classes derived from this class cannot then be instantiated unless all abstract methods have been overridden.

If your class is already using a metaclass, derive it from ABCMeta rather than type and you can continue to use your own metaclass.

A cheap alternative (and the best practice before the abc module was introduced) would be to have all your abstract methods just raise an exception (NotImplementedError is a good one) so that classes derived from it would have to override that method to be useful.

However, the abc solution is better because it keeps such classes from being instantiated at all (i.e., it "fails faster"), and also because you can provide a default or base implementation of each method that can be reached using the super() function in derived classes.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • `you can provide a default or base implementation of each method that can be reached using the super() function in derived classes` you can't use `super()` without `abc`? – Andrea Bergonzo Sep 20 '17 at 13:31
  • What it's saying is that you must use `super()` to reach method implementations in an ABC, not that you need to use `abc` in order to use `super()`. `super()` works with any new-style class. – kindall Sep 20 '17 at 18:41
  • I was only confused because it was "abc is better for motivation 1 and motivation 2" but motivation 2 is not `abc` specific :) – Andrea Bergonzo Sep 20 '17 at 21:35
  • motivation 2 is `abc`-specific in that the "raise an exception in the base class methods" technique doesn't play nice with having then do something useful. – kindall Sep 04 '22 at 14:54
12

Abstract base classes are deep magic. Periodically I implement something using them and am amazed at my own cleverness, very shortly afterwards I find myself completely confused by my own cleverness (this may well just be a personal limitation though).

Another way of doing this (should be in the python std libs if you ask me) is to make a decorator.

def abstractmethod(method):
    """
    An @abstractmethod member fn decorator.
    (put this in some library somewhere for reuse).

    """
    def default_abstract_method(*args, **kwargs):
        raise NotImplementedError('call to abstract method ' 
                                  + repr(method))
    default_abstract_method.__name__ = method.__name__    
    return default_abstract_method


class Shape(object):

    def __init__(self, shape_name):
       self.shape = shape_name

    @abstractmethod
    def foo(self):
        print "bar"
        return

class Rectangle(Shape):
    # note you don't need to do the constructor twice either
    pass  

r = Rectangle("x")
r.foo()

I didn't write the decorator. It just occurred to me someone would have. You can find it here: http://code.activestate.com/recipes/577666-abstract-method-decorator/ Good one jimmy2times. Note the discussion at the bottom of that page r.e. type safety of the decorator. (That could be fixed with the inspect module if anyone was so inclined).

demented hedgehog
  • 7,007
  • 4
  • 42
  • 49
  • 3
    How does this differ from [abc.abstractmethod](https://docs.python.org/3/library/abc.html#abc.abstractmethod)? – bcb Aug 05 '16 at 16:24
  • Not a great deal. Under the hood they're not too different I imagine. Pragmatically: "Using the abc.abstractmethod decorator requires that the class’s metaclass is ABCMeta or is derived from it.". – demented hedgehog Aug 06 '16 at 01:46
7

You can't, with language primitives. As has been called out, the abc package provides this functionality in Python 2.6 and later, but there are no options for Python 2.5 and earlier. The abc package is not a new feature of Python; instead, it adds functionality by adding explicit "does this class say it does this?" checks, with manually-implemented consistency checks to cause an error during initialization if such declarations are made falsely.

Python is a militantly dynamically-typed language. It does not specify language primitives to allow you to prevent a program from compiling because an object does not match type requirements; this can only be discovered at run time. If you require that a subclass implement a method, document that, and then just call the method in the blind hope that it will be there.

If it's there, fantastic, it simply works; this is called duck typing, and your object has quacked enough like a duck to satisfy the interface. This works just fine even if self is the object you're calling such a method on, for the purposes of mandatory overrides due to base methods that need specific implementations of features (generic functions), because self is a convention, not anything actually special.

The exception is in __init__, because when your initializer is being called, the derived type's initializer hasn't, so it hasn't had the opportunity to staple its own methods onto the object yet.

If the method was't implemented, you'll get an AttributeError (if it's not there at all) or a TypeError (if something by that name is there but it's not a function or it didn't have that signature). It's up to you how you handle that- either call it programmer error and let it crash the program (and it "should" be obvious to a python developer what causes that kind of error there- an unmet duck interface), or catch and handle those exceptions when you discover that your object didn't support what you wish it did. Catching AttributeError and TypeError is important in a lot of situations, actually.

Adam Norberg
  • 3,028
  • 17
  • 22
  • What about the abc module mentioned in the other answer then ?? –  Dec 08 '10 at 00:06
  • 7
    For what it's worth, Python *is* strongly typed, it's just dynamically typed. – Gintautas Miliauskas Dec 08 '10 at 00:09
  • 1
    Ack. This is the first time I'd heard of the `abc` module. I'm leaving this answer, though, because it applies to versions of Python before 2.6 (CentOS ships with 2.4), and duck typing still works here. – Adam Norberg Dec 08 '10 at 00:35
  • 1
    Yeah, it's a good point about the duck typing. Generally, programming in Python, you will generally be happier just calling the methods you expect rather than enforcing real type constraints. The `abc` is a nice option to specify *what kind* of duck you want, though. – kindall Dec 08 '10 at 01:11
  • python certainly is strongly typed. he is referring to static vs. dynamic typing. – Corey Goldberg Dec 08 '10 at 03:30
  • I don't think duck typing is the reason. PHP is also dynamically typed, and PHP5 supports abstract base classes in the normal way. This is one (rare) instance where PHP rather than Python is the one with the simple and elegant solution. – Canuck Aug 31 '12 at 13:19
7

You can use six and abc to construct a class for both python2 and python3 efficiently as follows:

import six
import abc

@six.add_metaclass(abc.ABCMeta)
class MyClass(object):
    """
    documentation
    """

    @abc.abstractmethod
    def initialize(self, para=None):
        """
        documentation
        """
        raise NotImplementedError

This is an awesome document of it.

Anthony Giorgio
  • 1,844
  • 1
  • 15
  • 17
Lerner Zhang
  • 6,184
  • 2
  • 49
  • 66