Programming and IT
Python: OOP
Object-oriented programming is a way of describing a problem through objects that have state and behaviour. In Python its usual four building blocks are simpler than in Java or C++: inheritance exists, private does not, and type compatibility is checked by behaviour, not by ancestry.
In this article
Inheritance: reuse instead of copying#
A child class gets all the attributes and methods of its parent and can add its own or replace existing ones.
=
=
return
=
return +
=
# 150 Peter
# True
super() refers to the next class in the inheritance chain. Calling
super().__init__(...) in the child's constructor is mandatory if the parent sets
anything up: without it the object simply has no such fields, and the crash
happens later and somewhere else.
Check types with isinstance, not type(x) == Employee: the latter gives False
for a subclass and breaks the whole idea.
Polymorphism and duck typing#
Polymorphism here means: the same call, a different result depending on the object's class.
return
return
# woof meow
Notice that Dog and Cat are not related by inheritance, and that is no
obstacle. Python does not ask which class an object belongs to — it checks
whether the object has the method it needs. This is called duck typing: if an
object quacks like a duck, the code treats it as a duck. That is why most of the
time you do not need a common base class at all.
When you do want to pin down a shared contract, use the abc module:
...
=
return ** 2
# 16
# TypeError: Can't instantiate abstract class Shape without an implementation
# for abstract method 'area'
Encapsulation: underscores instead of private#
The language has no private or protected keywords. There is a convention and
one technical trick.
name— a public attribute, part of the interface._name— internal; you should not touch it from outside, but the language does not stop you.__name— the name gets mangled: inside theAccountclass it becomes_Account__name.
=
return
=
# 500
# 500 — the "privacy" is bypassed in one line
= 0
# AttributeError: property 'balance' of 'Account' object has no setter
The double underscore was not invented to protect against programmers but to
keep a name from being accidentally overridden in a subclass. The real way to
restrict access is @property without a setter: the attribute can be read but not
assigned.
Composition instead of long hierarchies#
Inheritance ties classes together tightly: changing the parent breaks all its descendants. It is often better to make one object a field of another.
return
= # a car HAS an engine
return
# engine started
A simple rule for choosing: "is a" means inheritance (Manager is an Employee),
"has a" means composition (Car has an Engine). Multiple inheritance is allowed
in Python, and the method lookup order is visible in ClassName.__mro__, but in
application code it is almost always worth avoiding.
Practice: write a base class Shape with an abstract area, subclasses Circle
and Rect, put them in a list and print the total area with
sum(s.area() for s in shapes). How a class itself works is covered in the
article on Python classes, and iterating without a list
in the article on Python generators.
Step-by-step plan
- Parent and childWrite a base class with two fields and a subclass that adds a third via super().__init__.
- Override a methodReplace a method in the subclass and call the parent's version through super().
- A list of unrelated objectsPut objects of two unrelated classes in a list and call a method with the same name on all of them.
- Pin down a contractMake a base class with abc and check that it cannot be instantiated directly.
- Rewrite with compositionTake a three-level hierarchy and replace one level with an object stored in a field.
Start learning this in your own space
The plan goes into your repository: tick off stages, keep notes — the change history shows how far you have come.
Check yourself
1.Manager inherits from Employee. What does isinstance(Manager(), Employee) return?
2.Employee.pay() returns 100, and Manager.pay() returns super().pay() + 50. What does Manager().pay() return?
3.Inside the Account class an attribute is declared as self.__balance. Under which name is it reachable from outside?
4.Which relationship is better described by composition than inheritance: "Car has an Engine" or "Manager is an Employee"?
Sources
-
Classes and inheritance in the Python tutorialThe Inheritance and Multiple Inheritance sectionsfree
-
The abc module — abstract base classesABC and abstractmethod with examplesfree
-
The Python 2.3 Method Resolution OrderHow Python decides which parent's method to callfree
Was this helpful?