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

Eh, you can usually get away with just using hashmaps and lists. :)

That said…

class Foos:
    pass

f = Foos  # This is ok.
x = f()   # Same as `Foos()`
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.instance_method(args) is just shorthand for Class.instance_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.