Some Python Examples
← prev | next →     Top-level ToC     /oo.html     (printable version)

You can usually get away with just using hashmaps and lists.

* * *

That said…

>>> class Foos:
...  pass
... 
>>> f = Foos
>>> x = f()
>>> type(x)
<class '__main__.Foos'>

Terminology:

  • instance variables (an instance attribute that is not callable)
  • class variables
  • instance methods (an instance attribute that is callable)
  • class methods

You can access a class variable like TheClass.class_var or the_instance.class_var. They both work, but prefer the former.

Functions defined inside the class in the normal fashion result in instance methods. If you specifically want a class method, you need to use the @classmethod decorator.

1 Inheritance

BaseClass, DerivedClass
SuperClass, SubClass
ParentClass, ChildClass

Every method call tries to call the most-derived-class method (the lowest on inheritance tree) :

#!/usr/bin/env python3

class BaseClass:
    def __init__(self):
        print('Inside BaseClass.__init__().')
        self.x = 5
        
    def foo(self):
        print('This is BaseClass.foo() with x =', self.x)
        self.bar()

    def bar(self):
        print('This is BaseClass.bar() with x =', self.x)

class DerivedClass(BaseClass):
    def __init__(self, y):
        super().__init__()
        self.y = y
        
    def bar(self):
        # Overrides BaseClass.bar()
        print('This is DerivedClass.bar() with x =', self.x, 'and', self.y)

d = DerivedClass(87)
d.foo()

prints:

Inside BaseClass.__init__().
This is BaseClass.foo() with x = 5
This is DerivedClass.bar() with x = 5 and 87

TLDR: as long as you call super().__init__(...) instance attributes will be inherited in the way you expect.

Finer points to remember:

  1. __init__ methods are not “constructors”. They are initializers. The object has already been constructed by Python before __init__ gets to it. Among other things, you assign your instance variables inside __init__.

  2. If you don’t write an initializer (init() method), then Python just goes and uses the one in the base class. If you do create one, Python only calls that one (since it overrides the parent’s initializer) — if you want parent initializers called, you need to do it yourself (super().__init__(arg1, arg2, ..) — no need to pass self). And, of course, if you want to have instance variables which are present in instances of a parent class, you’re going to need to call the parent’s initializer to get them.

  3. Instance variables are not “inherited”, per se; you either create them (usually via init’s) or you don’t. If you want to make sure you “inherit” all instance variables, just make sure you call your parent’s init (and it should call it’s parent’s init, and so on), and those init’s are what create the instance variables. (No idea why Python doesn’t automatically do this.)

  4. Class methods and variables are inherited: SomeCls.foo will look for foo in SomeCls, then on up in parent classes.

  5. instance.method(args) is just shorthand for Class.method(instance, args)

  6. In Python 3, super() now works just as you’d expect, and you don’t have to pass self to it.