96

In Python, how do you make a subclass from a superclass?

mjv
  • 73,152
  • 14
  • 113
  • 156
dave.j.lott
  • 1,009
  • 2
  • 9
  • 5
  • 4
    Note that the Python changed the way you do subclassing, so there are 2 ways of doing it, and they don't mix. You will get an error if you mix. Read this post to see the difference: http://stackoverflow.com/questions/1713038/super-fails-with-error-typeerror-argument-1-must-be-type-not-classobj – Mark Lakata Jan 23 '13 at 22:59

13 Answers13

101
# Initialize using Parent
#
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

Or, even better, the use of Python's built-in function, super() (see the Python 2/Python 3 documentation for it) may be a slightly better method of calling the parent for initialization:

# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
    def __init__(self):
        super(MySubClassBetter, self).__init__()

Or, same exact thing as just above, except using the zero argument form of super(), which only works inside a class definition:

class MySubClassBetter(MySuperClass):
    def __init__(self):
        super().__init__()
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
thompsongunner
  • 1,140
  • 1
  • 6
  • 6
  • 6
    OTOH, some people caution against `super`, especially for new Python programmers (e.g., Lutz). I avoid it. – eric Feb 20 '15 at 20:27
  • 9
    The only reason to avoid `super` is if you don't understand the differences between how `super` works in Python, and how `super`/`parent` works in other languages. Admittedly this is not obvious to people coming from other languages, but I wouldn't conclude that that qualifies it as something to "caution against". It *does* work. It just works differently. Just read about what it actually does in Python before you complain about getting results you didn't expect. – TheAtomicOption Nov 16 '17 at 00:39
  • 6
    [This is the difference between the two methods to call the super class functions](https://stackoverflow.com/questions/21639788/difference-between-super-and-calling-superclass-directly) – Tiwtiw Mar 14 '18 at 09:15
  • [here](https://stackoverflow.com/a/70819745/2103784)'s this same example with `__init__` args – spatialaustin Jan 23 '22 at 06:43
77

A heroic little example:

class SuperHero(object): #superclass, inherits from default object
    def getName(self):
        raise NotImplementedError #you want to override this on the child classes

class SuperMan(SuperHero): #subclass, inherits from SuperHero
    def getName(self):
        return "Clark Kent"

class SuperManII(SuperHero): #another subclass
    def getName(self):
       return "Clark Kent, Jr."

if __name__ == "__main__":
    sm = SuperMan()
    print(sm.getName())
    sm2 = SuperManII()
    print(sm2.getName())
    
ewall
  • 27,179
  • 15
  • 70
  • 84
38
class MySubClass(MySuperClass):
    def __init__(self):
        MySuperClass.__init__(self)

        # <the rest of your custom initialization code goes here>

The section on inheritance in the python documentation explains it in more detail

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 5
    You only need to define that `__init__` method if want to add further code to it, otherwise the original init method is used anyway (although it's worth mentioning, and is perfectly valid code) – dbr Oct 22 '09 at 14:37
  • 2
    I think the question was vague enough to assume there might be further code added. Better to provide too much info than not enough and end up with another question when the OP implements it. :) – Matt Dewey Oct 22 '09 at 14:50
16
class Class1(object):
    pass

class Class2(Class1):
    pass

Class2 is a sub-class of Class1

workmad3
  • 25,101
  • 4
  • 35
  • 56
  • Cool. This is what I was actually looking for, i.e. a sub class with no extension / overrides to the super. – BuvinJ Nov 26 '18 at 23:07
11

In the answers above, the super is initialized without any (keyword) arguments. Often, however, you would like to do that, as well as pass on some 'custom' arguments of your own. Here is an example which illustrates this use case:

class SortedList(list):
    def __init__(self, *args, reverse=False, **kwargs):
        super().__init__(*args, **kwargs)       # Initialize the super class
        self.reverse = reverse
        self.sort(reverse=self.reverse)         # Do additional things with the custom keyword arguments

This is a subclass of list which, when initialized, immediately sorts itself in the direction specified by the reverse keyword argument, as the following tests illustrate:

import pytest

def test_1():
    assert SortedList([5, 2, 3]) == [2, 3, 5]

def test_2():
    SortedList([5, 2, 3], reverse=True) == [5, 3, 2]

def test_3():
    with pytest.raises(TypeError):
        sorted_list = SortedList([5, 2, 3], True)   # This doesn't work because 'reverse' must be passed as a keyword argument

if __name__ == "__main__":
    pytest.main([__file__])

Thanks to the passing on of *args to super, the list can be initialized and populated with items instead of only being empty. (Note that reverse is a keyword-only argument in accordance with PEP 3102).

Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
4

There is another way to make subclasses in python dynamically with a function type():

SubClass = type('SubClass', (BaseClass,), {'set_x': set_x})  # Methods can be set, including __init__()

You usually want to use this method when working with metaclasses. When you want to do some lower level automations, that alters way how python creates class. Most likely you will not ever need to do it in this way, but when you do, than you already will know what you are doing.

Pol
  • 24,517
  • 28
  • 74
  • 95
3
class Subclass (SuperClass):
      # Subclass stuff here
Wernsey
  • 5,411
  • 22
  • 38
3

You use:

class DerivedClassName(BaseClassName):

For details, see the Python docs, section 9.5.

aspiring_sarge
  • 2,355
  • 1
  • 25
  • 32
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
2
class Mammal(object): 
#mammal stuff

class Dog(Mammal): 
#doggie stuff
Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
1

Subclassing in Python is done as follows:

class WindowElement:
    def print(self):
        pass

class Button(WindowElement):
    def print(self):
        pass

Here is a tutorial about Python that also contains classes and subclasses.

dmeister
  • 34,704
  • 19
  • 73
  • 95
1
class BankAccount:

  def __init__(self, balance=0):
    self.balance = int(balance)

  def checkBalance(self): ## Checking opening balance....
    return self.balance

  def deposit(self, deposit_amount=1000): ## takes in cash deposit amount and updates the balance accordingly.
    self.deposit_amount = deposit_amount
    self.balance += deposit_amount
    return self.balance

  def withdraw(self, withdraw_amount=500): ## takes in cash withdrawal amount and updates the balance accordingly
    if self.balance < withdraw_amount: ## if amount is greater than balance return `"invalid transaction"`
        return 'invalid transaction'
    else:
      self.balance -= withdraw_amount
      return self.balance


class MinimumBalanceAccount(BankAccount): #subclass MinimumBalanceAccount of the BankAccount class

    def __init__(self,balance=0, minimum_balance=500):
        BankAccount.__init__(self, balance=0)
        self.minimum_balance = minimum_balance
        self.balance = balance - minimum_balance
        #print "Subclass MinimumBalanceAccount of the BankAccount class created!"

    def MinimumBalance(self):
        return self.minimum_balance

c = BankAccount()
print(c.deposit(50))
print(c.withdraw(10))

b = MinimumBalanceAccount(100, 50)
print(b.deposit(50))
print(b.withdraw(10))
print(b.MinimumBalance())
eric
  • 7,142
  • 12
  • 72
  • 138
Antiomic
  • 77
  • 6
  • 5
    This answer would be more helpful if you included an explanation of what it does – grooveplex Oct 19 '16 at 20:17
  • 4
    Although this code may help to solve the problem, it doesn't explain _why_ and/or _how_ it answers the question. Providing this additional context would significantly improve its long-term educational value. Please [edit] your answer to add explanation, including what limitations and assumptions apply. – Toby Speight Oct 20 '16 at 16:33
  • 2
    While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – andreas Oct 20 '16 at 18:21
0

this is a small code:

# create a parent class

class Person(object):
    def __init__(self):
        pass

    def getclass(self):
        return 'I am a Person'
# create two subclass from Parent_class

class Student(Person):
    def __init__(self):
        super(Student, self).__init__()

    def getclass(self):
        return 'I am a student'


class Teacher(Person):
    def __init__(self):
        super(Teacher, self).__init__()

    def getclass(self):
        return 'I am a teacher'


person1 = Person()
print(person1.getclass())

student1 = Student()
print(student1.getclass())

teacher1 = Teacher()
print(teacher1.getclass())

show result:

I am a Person
I am a student
I am a teacher
yuanzz
  • 1,359
  • 12
  • 15
0

A minor addition to @thompsongunner's answer.

To pass args to your superclass (parent), just use the function signature of the parent class:

class MySubClassBetter(MySuperClass):
    def __init__(self, someArg, someKwarg="someKwarg"):
        super().__init__(someArg, someKwarg=someKwarg)

You are calling the parent's __init__() method as if you are constructing any other class which is why you don't need to include self.

spatialaustin
  • 582
  • 4
  • 21