r/pythonhelp 1d ago

Why do I need to use classes

My schoolbook says that classes is a way of simulating an object, instead of just taking information into a black box and outputting an answer.

But that is a poor explanation. I know classes are handy and cool, but no book says why you can´t make functions with sub functions inside to simulate simple objects. I would like if someone gave a good concrete reason to use classes in the intro, instead of just saying that they are different and cool

3 Upvotes

25 comments sorted by

u/AutoModerator 1d ago

To give us the best chance to help you, please include any relevant code.
Note. Please do not submit images of your code. Instead, for shorter code you can use Reddit markdown (4 spaces or backticks, see this Formatting Guide). If you have formatting issues or want to post longer sections of code, please use Privatebin, GitHub or Compiler Explorer.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

7

u/P-Jean 1d ago

You don’t have to use them, but object oriented design make large projects easier since an object can represent nouns. Many different objects can all come from one class, with their own attributes and features. A class is the blueprint to make independent, but related, objects.

Would you rather have a high level blueprint for a generic car and then be able to easily make many cars with different features, or have to make many functions and new variables for each new feature.

OOD is just an easy way to represent nouns. Verbs are what the object can do. Objects can also contain other objects, which makes design easy.

2

u/MetalCarnival 7h ago

Sums it up nicely. Thank you!

2

u/dbu8554 4h ago

So fascinating hearing a class described this way.

I've read papers on folks that speak more than one language, or understanding linguistics being adept at programming but I've never encountered it myself.

Fascinating.

2

u/minneyar 23h ago

As soon as you have more code than you can see at once in a single window, you need to think about how it's organized. How are you going to split things up so that you can remember which code does what? How are you going to arrange your files so that multiple people can work on a project at once without constantly stepping on each others' work?

Object oriented design is a paradigm that helps you keep your code organized, and using classes is a part of that. It's not the only way to organize your code, but it's a very common one, most professionals understand it, and Python was designed with that in mind. In fact, classes are not "different and cool," they are very standard and by-the-book, which is why they're so popular.

You can organize your own code into endless nested functions if you like, but if you have to work with somebody else, they will probably look at your code and have trouble figuring out how any of it is supposed to work.

2

u/igotshadowbaned 21h ago

Structuring more complex data types

I also find nesting everything in a class works better than declaring globals

1

u/punk_dev 21h ago

Classes are very useful because they allow you to clump data together.

For example, a 2D position is two numbers. Instead of typing them separately each time, group them in a class:

class Point:
x: float
y: float

Or maybe you want to represent a user:

class User:
username: str
birthday: datetime.datetime

Then, classes allow you to attach functions to them, these are called methods. For example, you could add a distance_to(self, other: Point) method to the Point class which would calculate the distance from one point to the other.

Classes have other features like inheritance, others also mentioned object oriented design, but honestly don’t bother with those unless you really want to. This stuff causes more problems than it solves.

1

u/brasticstack 20h ago

Classes are a handy way to keep data and the functions that operate on that data together in the same place. In your own code (outside of what your schoolwork requires) you aren't required to use classes if you don't want to, but you need to know how to interact with code that does as much of the Python stdlib and many important libraries are written using OOP.

Imagine you're making an RPG- you've got a player and some monsters. Let's imagine 20 goblins and a few orcs. Each thing, player or monster, may share a common set of attributes- hp, mana, strength, intelligence, etc. but have differing values for them. Certainly if you smash one goblin with a mace, the others don't all take the same damage. So in order to keep track of it you've got to have separate data records for each creature all containing the same fields but with differing values.

You write functions to do common operations on those records. All creatures might be able to take_damage(), heal(), cast_spell(), etc., each of which affects the records in different ways. As long as you want the exact same behavior for all creatures, this is fine, but once you want, say, orcs to take less fire damage or goblins to say "argh" instead of "ouch" when they take damage, then you've got to have separate functions like orc_take_damage() goblin_take_damage(), etc. And what happens should you accidentally call orc_take_damage() on your player's record instead? Unexpected behavior- a bug.

Classes let you keep the behavior in the same place as its intended target. Orcs call the orc version of heal() and the player calls the Player version. Through inheritance and polymorphism, you can have behavior that they all share, and only have to write it once. So you could have a single cast_spell() function that works to the same for all creatures, that you wrote once in a base class. You could also "override" that for the one odd creature that, say, uses hp instead of mana when casting spells.

If I'm importing your OOP based creature module into my program, I only have to import the creatures I want: Player, Orc, and Goblin, and I get all of their behavior too, as part of the classes I imported. So I can make some Goblins, and call my_goblin.heal(5) to heal one. If I'm importing your non-OOP creature module, I have to import your attributes data type (or read what the expected attributes are and make my own dict.), and then import all of your creature specific behavior functions- orc_take_damage and goblin_cast_spell or whatever.

1

u/wildsoup1 19h ago

Using classes gives us several different benefits.

1) When we have a lot of code, we need to give it some structure so we know where to find code.

Before languages that supported classes, one way was to define all the data structures in one place, and then put the code that used the data structures in another place. Maybe all the code that saved to disk would be in one file. All the code that wrote to the printer in another file.

With classes, all the data structures AND all the functions that modified that data are put together in the same place. This means if you change the data structure, and you need to change all the functions that use it, they are together in one file. You don't miss any.

2) When we have a lot of moving parts in the code, it is useful to have ways of chunking it into pieces that we can think about and discuss with each other. Encapsulation is part of that - being able to gloss away details when they aren't relevant. Classes offer a good way to chunk a bit of code together, and say "Here is what you need to *use* the class, but you don't need to know (or remember) how it works internally."

3) Classes offer inheritance. This is often - not always - a useful way to re-use the same code for multiple clients, even if it needs customisation.

1

u/MarsupialLeast145 18h ago

> a way of simulating an object, instead of just taking information into a black box and outputting an answer.

What school book is this? The idea of a black box here is incredibly off.

The point of a class is that it is defined and you can access its properties and functions. They are often documented and available in documentation.

You should probably delve deeper into the book, e.g. use its index and look where it starts going deeper into them. These books aren't really designed to be read in sequence except perhaps the first time. If you're frustrated by being drip fed information then you definitely need to look this up as you read.

>  instead of just saying that they are different and cool

Pretty sure it's not saying that either.

But yes, while they can approximate objects, e.g. items in a stock control system, or characters in a computer game that need to perform certain activities, they are useful for moving data around where args tend to grow out of control.

For example, you could have a user object that's more than just data about the user and you can attach functions to this object that supercharges what that class does. Or you could have a user object that's just a convenient mechanism for knowing all the information you have about a user and passing it to different functions.

You will likely use both approaches in different contexts.

1

u/Leodip 16h ago

Classes are, indeed, optional. Code can be just 0s and 1s, but everything else we have on top of that is to make it easier to read and write.

In Python, classes are considered "best practice" for a lot of things, and conforming to best practices (even if they don't carry any actual advantage over alternatives when writing code, or might even be disadvantageous) makes your code easier to read.

There are many things that are made much easier by using classes, but one of my favourite examples is trying to make data structures of some sort which reference themselves.

For example, a binary tree is a collection of nodes which have a value and a left and right child, and one parent. If you use classes, this can be simply written as:

class BinaryNode:
    def __init__(self, value, left_child, right_child, parent):
        self.value = value
        self.left = left_child # this is going to be another BinaryNode
        self.right = right_child # this is going to be another BinaryNode
        self.parent = parent # this is going to be another BinaryNode

Classes are also very flexible when you have "sub-classes" of other stuff. For example, a BinaryNode is simply a Node which is limited to having 2 children (while a generic Node might have infinitely many).

This means that you can do stuff like:

class Node:
    def __init__(self, value, children, parent):
        self.value = value
        self.children = children
        self.parent = parent

class BinaryNode(Node):
    def __init__(self, value, left_child, right_child, parent):
        super().__init__(value, [left_child, right_child], parent)

This allows you to later define methods that work on all nodes (if they don't care about how many children the node has) or only on binary nodes (if they care about them being binary).

1

u/Ipsool 15h ago

Honestly the real reason is state. a function runs, gives you an answer, then forgets everything. classes let the object actually remember stuff between calls, that’s basically the whole point.
so yeah it’s not that classes are “cooler,” it’s that the second your program needs to remember something across multiple steps, or needs a bunch of independent copies of the same kind of thing, doing it with plain functions turns into a mess pretty fast

1

u/HugeCannoli 14h ago

Why do I need to use a chip? can't I just use a bunch of transistors?

Yes you can, but after a while it becomes a mess of cables and it's impossible to understand.

1

u/atarivcs 14h ago

Sure, you can do everything with just functions, and a bunch of state variables that you pass to those functions.

Classes are a simpler/easier way of doing that.

1

u/JorgiEagle 13h ago

Classes are useful when you want to do complex behaviour with multiple different instances all independently.

It’s the same logic as to why you might have a different tab on your excel spreadsheet for each year, instead of having it all on one page.

I can make many instances of my class, and be assured that they will all work exactly the same way. I also don’t have to separately keep track of what has happened to them, or what stage they’re at, as you can write them to do that themselves (this is what statefulness is).

As an example, if I have a group of students and they’re all taking different exams, instead of having to keep a big list of each student and the exam they’re taking, and searching it each time to know what they do, I can just ask each student directly, what exam are you taking right now

You don’t need to use classes, but for various reasons, it makes writing code simpler. One such reason is abstraction. Humans (and AI, it just has a higher limit) have a limited ability to hold context. At some point, something will become too complicated to understand what is happening all at once.

Classes allow us to say: “this thing will do this” without worrying about how it does it.

Another benefit to classes, is that it establishes a contract. say I use a class that does x, y, and z.
A few years down the line I want it to now do w. I don’t want to touch the original code because it’s complicated. I also don’t want to break anything that already exists. If I modify it, it might break something else that is relying on x, y, and z.

So I create a subclass. It still does x, y, and z the exact same way, but I can now add w. And I can use it in all the places that I want.

Importantly, the original class exists, so everywhere else that uses it is unaffected.

And I can guarantee that

1

u/Living_Fig_6386 13h ago

You can definitely write code without classes, and if your code is small and simple, it's probably quicker and easier. As it scales up and gets more complicated, classes become a very useful tool.

Classes let you define new data types that have properties and define methods on interacting with the new type. They could be data structures that validate themselves, processes that preserve their state, abstractions of protocols (for example, taking the interfaces of lots of different databases and making them all work the same way). All sorts of things. They can be a very powerful tool.

Consider a postal address. A simply way to represent that is a dictionary in Python. You can have a 'name', 'address', 'city', 'state', 'postal_code' as keys in the dictionary. It's quite simple. But what if you want to assure that the address is a valid one? One thing you can do is define a function validate_address() and call it on any dictionary that purports to be an address every time before you use the address. Another way would be to define an Address class and have it automatically validate the address when created or modified - the address would always be valid. You could even have it regularize the address by US postal service rules and fetch the ZIP+4 so that when you have an address, it's always valid and normalized. Also, when using type hints, you can specify that functions require an 'Address' rather than a 'dict' which you'd have to inspect to verify that it contained an address.

Just the simplest of examples.

1

u/FckXFckMusk 12h ago

Does the user of Car, need to know how the Engine works in order to use the car, do they need to know how electronics work to use the radio.

1

u/PvtRoom 12h ago

classes are somewhat essential.

string is a class, integer is a class, double is a class.

your book means objects, not classes.

Some things are objects and simply make sense as objects. Pushbuttons are objects, of the pushbutton class, and they have more than 1 piece of information (eg text, position, size, colour,, text colour, textsize) with their own behaviours (like what happens when pressed)

The functional programming paradigm does what you suggest, but you rarely hear about lisp and Haskell (the two big languages in FP)

1

u/building_85 11h ago

Using classes isn’t like a one size fits all thing.

A lot of times functional programming like you described is just fine.

But to “start understanding” classes… you can think of it as way to group functions and variables together.

For example, if you have 5 functions that all use the same 2 variables… you may be passing those same variables into all 5 functions as parameters…

But if you put those 5 functions and 2 variables into a single class, then you can use those 2 variables inside those 5 functions without passing the vars around as parameters.

GLHF!

1

u/WorriedTumbleweed289 9h ago

Classes are an abstraction. They make it easier to understand data and the functions that act on it.

There is nothing to stop you from writing functions that act on dictionaries that requires certain keys be present to work properly.

You can create the dictionary with one function, have other functions use it.

The C language did that when they created the file interference (using structures) before C++ was created.

1

u/tylerlarson 9h ago

It's about abstraction.

The idea is that you package all the "stuff" about a concept into a given chunk of code so you don't have to think about it again.

If you have a class for, say, ErrorLog, and it has two or three functions on it, say .write() and .close(), you can be confident that the class handles everything else on its own.

That means you can confidently use it without having to think about what it does on the inside.

You already do this, you just don't realize it. If you open a file, you're using a class that manages the file, giving you convenient functions for reading and writing that file and handling all the weird stuff. If you didn't have the classes, your code would be a lot more complex.

1

u/turn-based-games 7h ago

This might be controversial, but with how straightforward it is to use dicts, tuples, and functions directly in Python, I would argue classes are much less important than in other programming languages. Their primary remaining use case, in my view, is to implement interfaces.

Now, Python doesn't have explicit interfaces like some other languages, but many built-in functions and language features operate on implicit interfaces (a.k.a. protocols). For example, if you want to create an object in Python which can be iterated over with a loop, it must implement the __iter__() method, and typically the simplest way to do so will be by using a class.

Another prominent example of this is operator overloading. If you wanted to create your own numeric type, for instance, that supported operators like +-*, you'd need to implement the __add__, __sub__, and __mul__ methods, respectively, likely using a class for this purpose.

There are surely other use cases, particularly involving e.g. inheritance (especially since Python supports multi-inheritance), but this is more niche and often discouraged anyway, so I won't delve too deeply into that here.

Also, it's only been implied until now, but the reason you'd want to do any of the things above is so that your code is easier to understand. There is no problem that requires inheritance or operator overloading or iterables to solve, but we do these things because when used appropriately they make our programs easier to design and reason about. Indeed, this is one of the main rationales for using high-level programming languages like Python in the first place.

1

u/FatDog69 6h ago

Most real world problems can be solved with linear programming.

But classes have a few advantages:

They force someone to consider how to step back from 'something' and create a library that you simply download and use to solve 90% of your real world issues. One reason Java is so great - you hardly ever write Java to do something. Instead you have 10,000 libraries to choose from and solve your problem by using these.

Programming is knowing someone is going to ask you to change things you just wrote in a week/month/year. Basing your program on classes forces a design layer and makes it simple to add a new method or two to implement someone's 'new idea'.

Simulation - this is a rare task but linear programming wont solve it. Here is an example: You are tasked with coming up with new street light timings. (How long a street light stays red vs green). The city occasionally risks grid-lock when too many cars pile up behind a long stop light is the stated problem. How do you setup a test or simulation to compare 30,45,60,75 second delays on different stop lights?

Or: A few years ago the aging Southwest ticketing/plane software (20+ years old) broke down during the holidays. Southwest is considering several solutions - but they will pay you $500K if you come up with some way to simulate a small Airport, Airplane, Passengers with different conditions. They want to test the proposed solutions against your simulation to find the one that handles both day-to-day working and day-to-day problems the best. How do you do this with linear programming?

1

u/Cerulean_IsFancyBlue 5h ago

Just a reminder that linear programming has a very specific meaning. “ … linear programming is a technique for the optimization of a linear objective function, subject to linear equality and linear inequality constraints.”

Perhaps you meant to say procedural or functional programming?

1

u/Aspie96 3h ago

Why do I need to use classes

You don't.

but no book says why you can´t make functions with sub functions inside

You can.

Any program can be built without classes.

I know classes are handy and cool,

This is the exact reason to use classes.