Dan Bader

6 things you’re missing out on by never using classes in your Python code

Maybe you’ve been using Python for a while now and you’re starting to feel like you’re getting the hang of it. But one day you catch yourself thinking: “What about classes?”

a motivating picture of a snake

You see other developers at your company or online discussing the merits of object oriented programming. “Classes are incredibly useful and everyone should know about them,” they say.

You’re beginning to get worried about writing your code the right way:

“I’ve never defined a class… I mean I know how to get stuff done quickly. I use functions and modules for everything, often many small functions whose output I feed into another. I simply don’t use classes because I never felt the need for them.

What am I really missing out on?

Am I shorting myself on something by never using classes in my Python code?

I noticed that this is a common question for Python developers with a (data) science or numerical computing background.

You may be familiar with languages like R or Matlab and you haven’t really felt the need to use classes in your day to day work writing Python code. Most of your computations are sequential in nature and you found that a structured programming style worked just fine for the category of analytical problems you’re facing.

But still … there’s this nagging feeling in the back of your head – “What am I really missing out on by not writing classes?”

Let me try and help you out there. In this post I’m going over 6 things you might be missing out on by never using classes in your Python code. I’m not an OOP zealot by any means but I figured a post like that would be helpful to some folks in the Python community.

Alright, let’s dive in!

1. Easier collections of fields

If you categorically avoid the use of classes it’s easy to find yourself in a situation where you just re-invent your own “ad-hoc classes” using other built-in data structures, like lists or dicts.

For example, you might end up with lots of lists or dicts that share the same keys to access different kinds of data associated with a single logical object:

car_colors[23] = 'yellow'  # Color of Car 23
car_mileage[23] = 38189.4  # Mileage of Car 23

By switching to classes you could have a single list of objects, each of which has several named fields on it to address the associated data:

cars[23].color = 'yellow'
cars[23].mileage = 38189.4

Instead of using lists and dictionaries that happen to contain all your data you can keep all of it under one roof, which makes accessing and passing these objects around much more convenient.

You’ll also no longer need to pass around big tuples of stuff from function to function.

(Side note: You may want to go and learn more about Python’s namedtuple objects which reduce the amount of boilerplate class-code you need to write if you just want simple C-style records of fields. Notice that namedtuple objects are implemented as Python classes internally.)

2. Simpler domain models

It’s easier to think about a domain model with a number of classes that have some relation to each other, than it is to think about lists and dictionaries that are linked together by shared keys and indexes.

Some domains lend themselves well to being modeled with classes, for example GUI controls. I found that with an object-oriented approach the domain model sometimes becomes easier to discuss and reason about with other developers. And that’s always a good thing.

3. The ability to chain objects together and let them interact in an expressive way

This is where object oriented programming really shines – when the objects you’re dealing with have behavior on them. For example, a button that can be clicked or a car that can accelerate and brake.

In this case it helps if you encapsulate those behaviors by making methods on your Button and Car classes so that other objects can call those methods and change the Button’s or Car’s internal state without knowing how that operation is implemented.

Especially when you have a lot of behavior on your objects it’s helpful to have it all in the same place and under one roof that is the object itself. That way you can chain objects together and let them interact in an expressive way that’s hard to emulate in a procedural coding style.

For an example of this compare the following two code samples implementing the same sequence of interactions.

The OOP version:

if not garage.is_full:
    garage.add(my_car)
    my_car.turn_off()
    garage.close()

vs the non-OOP / procedural version:

if not is_garage_full(garage):
    add_car_to_garage(my_car, garage)
    turn_off_car(my_car)
    close_garage(garage)

4. Custom exceptions

If you want to define custom exception types in Python there isn’t really a way around using classes. Custom exception help communicate the programmer’s intent more clearly and they’re a great debugging aid.

Here’s an example of a more specific exception type that’s based on one of Python’s built-in exceptions:

class ValueTooSmallError(ValueError):
    pass

I’ve recorded a quick screencast tutorial that shows you how to use this technique to make your code more readable:

» Subscribe to the dbader.org YouTube Channel for more Python tutorials.

5. Fitting in with the coding style used by your colleagues

Another good reason for learning about OOP is that it is still a popular paradigm in the programming community. Therefore it is likely that you’ll be working with an object-oriented code base at some point in your career.

It can be difficult to integrate and maintain code in a single code base that was written in a different style, let’s say functional vs object-oriented.

If you’d rather avoid being the one engineer sticking out with an idiosyncratic coding style then it might be worth familiarizing yourself with OOP and classes.

6. Useful OOP design patterns

There’s a large body of OOP design patterns out there that can speed up development and improve readability. Design patterns are not a panacea and as with all things they can be overused – but in some situations being able to apply common design patterns will be helpful.

I’m going to shamelessly plug one of my open-source Python modules, schedule, as an example here. It uses the Builder pattern to let you schedule periodic jobs with a developer-friendly API:

import schedule

def job():
    print("I'm working...")

schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)

Final thoughts…

With all of this keep in mind that OOP isn’t the only programming paradigm in the world. You might be lucky and not miss out on much extra productivity even if you’re not well-versed in object oriented programming. If you don’t feel the need to use classes then there might not be a real reason to use them in your problem domain!

However, to be a well-rounded engineer I believe it’s necessary to know the basics of OOP and object design.

I like to think of classes and OOP as yet another tool in the toolbox. Sometimes it will be exactly what you need to get the job done – and sometimes it won’t.

And that’s okay.

Object-Oriented Programming in Python: The 7 Best Learning Resources

Free cheatsheet—just enter your email address below:

This article was filed under: oop, programming, and python.

Related Articles:
  • Abstract Base Classes in Python – Abstract Base Classes (ABCs) enforce that derived classes implement particular methods from the base class. In this chapter you’ll learn about the benefits of abstract base classes and how to define them with Python’s built-in “abc” module.
  • Make your Python code more readable with custom exception classes – In this short screencast I’ll walk you through a simple code example that demonstrates how you can use custom exception classes in your Python code to make it easier to understand, easier to debug, and more maintainable.
  • A countdown timer extension for Alfred – I wrote a countdown timer extension for the Alfred application launcher for OS X. The extension is open-source, written in Python and uses Mountain Lion’s user notifications.
  • Monochrome font rendering with FreeType and Python – For my Raspberry Pi internet radio project I needed a way to render text suitable for a low resolution monochrome LCD. This article describes how to render 1-bit text using FreeType and Python.
  • Setting up Sublime Text for Python development – I recently started using Sublime Text 2 more and more as my main editor for Python development. This article explains my setup and some tweaks that make Python programmers happy.
Latest Articles: ← Browse All Articles