Classes are a bit overwhelming. How far can I get with just functions?

Right now, I find classes overwhelming and wanted to know: How far can I get by in python without classes? I know why they exist, but trying to think up when to use a class, is stressing me out a bit. I’m probably more used to the ideas of procedural programming like C, so I can think better if I just break everything up into functions.

Am I overthinking when to use a class? Like trying to force a cube into a round hole when a class might not be necessary?

You’re fine.

You can get pretty far with just functions. In fact, I would even argue that languages that force the developer to use classes for everything (such as Java) have a problem of “If the only tool you have is a hammer, every problem looks like a nail.”

Beginner programmers tend to write what I call “Choose your own adventure” code: it relies on flow control statements like loops, if/else branching, and functions. This is fine when you’re starting out.

As you learn data structures (even just lists and dictionaries) you’ll begin to see that creating a data model for something is better than the CYOA style. For example, if you want to make a chess program, you could represent the chess board as a dictionary: the keys can be strings that represent a space on the board (like 'A7' or 'E3') and the values could be strings to represent the piece at that space (like 'bK' for black king or 'wN' for white knight.)

A lack of a 'A2' key would mean there is no piece at the A2 space. Or maybe your chess dictionary does have keys for all 64 spaces on the board and 'A2': None is a key-value pair that means A2 is empty. Or a key-value pair with a blank string like 'A2': '' means A2 is empty. It just depends on what you think makes sense for your program.

This is how you model a real-world thing (the chess board and pieces) as data (a Python dictionary with string keys and string values).

Then instead of CYOA code, you write code that performs actions using this data. And here’s where classes come in: if you have a bunch of functions that always act on the same data structure, it can help to bundle that data and those functions into a class. (And we call functions in a class “methods”, even though they’re basically the same thing.)

For example, I have a free Python book where I wrote a small Tic Tac Toe program where I use a dictionary to represent the X’s and O’s on a Tic Tac Toe board: Chapter 15 - Object-Oriented Programming and Classes (see the " Non-OOP vs. OOP Examples: Tic-Tac-Toe" section)

Notice how a bunch of functions like isBoardFull() and isWinner() all take a “board” dictionary as their first argument. Since you’re always passing this same data structure to these functions, it makes sense to make a TicTacToeBoard class that bundles the dictionary and these functions together. Then you can use the self argument (called this keyword in other languages) to reference that TicTacToeBoard object’s data.

Classes are a way to organize your code. All of this is really only useful when your programs get into thousands of lines of code or more. You can read the rest of the chapter to understand “why do we have classes?”

But you can just keep using functions for now. Once your programs become large and kind of unwieldy and you start thinking, “Is there a better way to write this?” then the value of classes will be more apparent.

7 Likes

Just to expand on what @AlSweigart said. The only time you really need classes is when you need more advanced data structures. Sometimes you can handle that with builtins like NamedTuple but sometimes you need more including the ability to have the class do something. As you get better at Python you’ll figure out when you need a class and when you don’t. A lot of very good Python code is a mixture of functions and classes - and very often the classes don’t have methods, they’re just better ways to represent the data.

Hello,

I suppose it all depends on what you are doing. Per your posting, you are familiar with C procedural coding. I guess this is from embedded programming? For this, yes, procedural programming works well for this type of application. You can, of course, get by with other applications.

Classes are a bit intimidating at first and it does take a while to getting used to, I will admit as I had my own challenges to overcome when I was first learning them. Even if you don’t start right away with using classes in your applications, I would advise to at least begin learning the fundamentals so that you become familiar with the concept of qualification, which is what you will be doing when importing other tools (i.e., libraries such as tkinter, numpy, panda, etc.).

Qualification has to do with the idea of using an attribute of a class by way of prefixing it with a class name and a “.”. For example:

from a_namespace import class_name

ans_1 = class_name.attribute_1  # employing a class attribute to obtain its value

ans_2 = class_name.method_1(100)  # pass a number to the class method

So, if you understand classes from a qualification point of view, you’ll understand a little bit more of what is going on behind the scenes when using external libraries. This is how you get access to attributes and methods to employ in your application.

Now, this concept is but a small nugget as classes can be very extensive and versatile. Begin by creating simple objects (ahem, instances of classes) and practice over and over again with different variations from your starting class example. The steps to follow are: modify, test and observe. Once you understand what a class is doing in isolation, then gradually begin employing them in longer scripts. Eventually, you’ll begin to appreciate their utility.

Functions are fine but I use a class to hold 50+ option variables to every function, including whole input and output file arrays (a file as a list). It’s handy having all my options in one variable which is a class instance.

Python is very good managing memory and I haven’t had a problem yet. Of course I haven’t yet rewritten a program which holds 100,000 lines of a spreadsheet as part of that class instance either.

They’re effectively the same:
method(self, *args, **kwargs)
self.method(*args, **kwargs)

As long as all your data structuring can be known in advance, you can do anything with functions.
When you have states that are modified by instructions, you can have global variables or collections. The classes are useful for keeping instructions and data together in dedicated objects.

My take on this…

I think you can do anything with just functions, in the sense that any software you can think of can probably be written without using classes at all. I believe that one of the first limits you will encounter will be when you will want to use libraries, because a lot of APIs of libraries are based on classes, so to use those libraries you will have to use classes. Now in my experience, in most cases it is possible to somewhat ignore that a library’s API is class-based.

do not get discouraged, classes are blueprints of objects, and the functions are inside the objects, representing things this object can do.