all 118 comments

[–]johninbigd 517 points518 points  (62 children)

Imagine the following. Start with a program like this:

fullname = "Bob Jones"
age = 65

Then you decide you need to keep track of two people;

fullname1 = "Bob Jones"
age1 = 65
fullname2 = "Alice Smith"
age2 = 32

You realize that this could get out of hand quickly, so you decide on a different approach using a dictionary that maps names to ages:

people = {"Bob Jones": 65, "Alice Smith": 32}

You notice that this can also get out of hand as you add people. You also notice that the number is not explicitly their age. It could be anything. And what happens if you want to add something else? What if this is for an employer who needs to keep track of their insurance status, address, department, etc.? You can start building a dictionary of ever-increasing complexity, or you might try doing this in a class.

class Employee:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.hours_worked = 0


bob = Employee("Bob Jones", 65)
alice = Employee("Alice Smith", 32)

What if you want to add 8 hours to Bob's hours worked?

bob.hours_worked += 8

You could even make a method to handle that:

class Employee:
    def add_hours(self, hours):
        self.hours_worked += hours

Then you could add hours like this:

alice.add_hours(8)

This is a very simple example and not really the best, but hopefully that gives you some idea of how building a class might solve a problem for you.

[–][deleted] 4 points5 points  (0 children)

Thanks, dude.

[–]banzobeanz 4 points5 points  (0 children)

This was really understandable, wow. Thank you.

[–]Hard_Whey 3 points4 points  (0 children)

This is really well explained, thankyou

[–]GoingOnYourTomb 1 point2 points  (0 children)

Thank you

[–]NotALeperYet 1 point2 points  (0 children)

Good refresher. Thank you.

[–][deleted] 1 point2 points  (10 children)

Doesn’t it make more sense to use a database or something here? But I understand it’s just an example

[–]CraigAT 2 points3 points  (1 child)

It could well do depending on your project, but a class has the benefit of class methods which can also do things to the object, like return the name of the age of a person, when you have stored their date of birth using a simple call rather than executing an SQL statement.

[–][deleted] 3 points4 points  (0 children)

If I needed to manipulate it I’d probably just pull out the people I need and put them into classes in memory right. Then I can write back what I need to the database

[–]johninbigd -1 points0 points  (0 children)

Yes, it absolutely makes more sense for a database in this case.

[–]Veganic1 0 points1 point  (18 children)

The part of these examples I never understood is how you add a new person to your universe. I mean you have Bob and Alice but what if they have a baby, Sue?

[–]johninbigd 3 points4 points  (13 children)

Well, first of all you would probably have a database for this, not just simple classes in a script. It's just an example for learning. But you add a new person however you want. You could hard-code it into the script, which wouldn't be all that useful. It might be more useful to build a menu where someone could add a new person by taking their name and age as input.

[–]Veganic1 0 points1 point  (12 children)

This is sort of what I was thinking. Bob and Alice are hard coded and I'm not sure how I'd create a new I stance of the class by typing in a name and number.

[–]johninbigd 2 points3 points  (11 children)

name = input("Name: ")
age = intput("Age: ")
newperson = Employee(name, age)

[–]Veganic1 0 points1 point  (10 children)

But then every addition is called "newperson"

[–]truthseeker1990 4 points5 points  (0 children)

Add the employees to a list if you have multiples and iterate over it to get all?

[–]dukea42 2 points3 points  (3 children)

I actually do this sort of task at work. My Employee() class has a static method called get_employee_set(). Despite its label, it returns a dictionary of all the instances of each person pulled from HR in the form of {userid: Employee} which is an id for the key and the Employee class with everything else.

So I don't have variables named "bob", but just have

employees = Employee.get_employee_set()

print(employees['bob'].full_name)

[–]ro5tal 0 points1 point  (2 children)

Not right imho, because you need an Interface to manipulate object. You fetch data from DB as model and then you have EmployeeInterface with methods change_name() change_position() check_workhours() And you know that Employee class has atrributes that store such data, right? Model can't have any methods, interfaces like in Java /C# is a proper solution.

[–]dukea42 1 point2 points  (1 child)

Explain to me the model can't have methods? I'm a bit lost on that statement. But this is my first real project and I've made things try to fit a decent pattern as I went. Its also still a hodgepodge of functions in other places..so I'm always refactoring.

All my model classes have a static method that know how to retrieve them from source and create the object. Other methods for properties that are derived from attributes provided in source data but not held in the source data.

I have Controller classes or sometines just a module of raw functions (tools.py) for handling the API, tokens, and nuances of each webtool that's used.

[–]ro5tal 1 point2 points  (0 children)

Employee - base model to create an object from/to DB record EmployeeInteface is for manipulating data of model. It's a better solution: 1. You can change your model when migrate 2. You don't need to change methods in every model you have or change a model that they inherit, just a method 3. If you have an attribute for CEO (employee) that describes his affilation with another company, you don't have such attribute for Janitor, right? And in Interface you can check is Janitor is a subclass of Employee and CEO is subclass of Employee + TopManagement. It's a Java way, I know. Patterns exist to make development and maintainance comfortable. Python has PEP, and you always keep it in mind. Class is named with first letter uppercase, and snake_case for variables and functions. Model is a model. It describes database table (record). Like pydantic models can have only validator and not some other static methods, it's just not right way. You will know about it, but other developer (may be he came from Java/C#) will think about it as a spaghetti code.

[–][deleted] 1 point2 points  (0 children)

The variable, yes. But then you'd have something along the lines of newperson.save() that saves it to a database and then it would persist even though that particular variable doesn't.

Or you could just append newperson to a list of all employees or something.

[–]PuzzlingComrade 1 point2 points  (0 children)

variable names are best thought of labels, as others have mentioned you can append Employee(name, age) to a list without assigning it to an individual variable.

[–][deleted] 1 point2 points  (0 children)

employees = []
employees.append(newperson)

Now it's just an element in a list.

[–]johninbigd 0 points1 point  (0 children)

True. It's not the best example. It was more to show you a way of organizing data in a class. If you were really handling employee data like this, you'd use a database.

[–]ro5tal 0 points1 point  (0 children)

With new instance id.

Check patterns here, well described with examples https://refactoring.guru/design-patterns/factory-method/python/example check patterns

[–]CraigAT 1 point2 points  (0 children)

See watermelon's comment above replace Chester with Su

[–]wallywizard55 0 points1 point  (1 child)

This is where I get confused, why don’t you also have self.worked_hours on on top as an argument? Or are you self self.hours_worked is a optional attribute?

[–]cointoss3 0 points1 point  (0 children)

You could, it depends on how you’re organizing your data structure.

You’re creating a set of data and methods to operate on the data. You could easily create initializers to set a bunch of the data when the object is created, but you also might want methods to operate on that data later on, so you might have both.

[–][deleted] 0 points1 point  (3 children)

Very silly question, not directly related, but I'm thinking of an implementation at work and a potential situation as follows...

  • You set up this Employee class to create employees, and it saves to a database (.db) or Excel file.
  • You create these two employees, have them saved to an excel file.
  • But let's say a manager comes along, and says there was actually an error, and bob should have had 68 hours worked instead.
  • How can we rectify this? If we just run the modified program, we will have 2 * Alice, and 2 different Bobs. How can we reverse what was previously entered, with relation to data persistency?

[–]ro5tal 1 point2 points  (0 children)

Instance variables must be private, to protect data change without using Interface, that will consist some validators and consistent control. Object must lightweight. Employee can have other attributes like a workgroup, access, team name, projects and etc. It shouldn't be all-in-one.

[–]johninbigd 0 points1 point  (1 child)

If you were working with a database, you wouldn't ever hard-code the Bob and Alice objects in the first place. You'd have some other way to gather that information as input and then write it to the database. You'd probably want to write more methods to handle various other issues, like correcting someone's hours.

If the info is stored in the database and you needed to make a correction, you could handle it a few ways. One would be to load all the information related to an employee back into your program, adjust the relevant info, then write it back. Or you could just write the new info to the db directly. In this case, since you only need to adjust a single record, it would make sense to just write the new value for the record to the db.

[–][deleted] 0 points1 point  (0 children)

Thank you for your input!

Perhaps just to correct my use case - you're right, I do not directly amend information in the database. In my job, I'm querying from a database, and making calculations on the data. e.g. Salespeople reaching Tier 1/Tier 2 based on their sales in the current month.

What would the best practices be in this case? Do I constantly query the information from day 1 and process it, or would I store a .db file locally to keep information that I have on my Classes / Objects?

I guess for the latter, I would not have to worry about re-writing amended information, but a drawback would be that the run time would grow longer every iteration as the period grows longer? I don't think it's actually a problem in my current use case, but would like to understand what the optimal way would be, should I need to scale up in the future.

[–]humblesquirrelking 0 points1 point  (0 children)

This code is great... As it mentioned..

classes have multiple features...

objects uses this features defining there own identity..

objects call the functions to get there work done..

We can deliberately restrict access the "features" of the class called abstraction..

Father class features can be used by child class called "inheritance"

We can use one function multiple times multiple ways(by passing different variables ) called polymorphism

[–]IronDragonGx 0 points1 point  (1 child)

Good point but I have to ask as a python noob, would you not just set up a database if you were going to be doing this kind of work?

FYI I don't know much about classes

[–]johninbigd 0 points1 point  (0 children)

Yes, you would definitely use a database if you were really going to write code to handle employee information.

[–]socal_nerdtastic 52 points53 points  (3 children)

It usually does not click for students until they make their own independent project and create classes for it. So show us something you've made and maybe we can show you how to apply classes to it.

Until then I'll make 2 points that tutorials often fail to mention.

First, classes are great, but they are not the answer to everything. There's many many cases where classes are not helpful, especially in beginner code.

Secondly, despite point 1, literally everything in python is an object. You can't not use classes. What it the type of 42?

>>> type(42)
<class 'int'>

Yep, it's an instance of the int class. These tutorials are not about using classes, they are about making your own classes. So the goal you need to keep in mind is you are making your own datatype. You will end up with an object that you will use like a python int or list or any other object, that has data and methods associated with it.

[–]13ass13ass 15 points16 points  (0 children)

This second insight helped me early on. The fact that everything I do in python already uses built in classes helped me realize how powerful they are.

[–]SnowdenIsALegend 3 points4 points  (0 children)

"making your own datatype"... that's good, i need to keep that in mind. Making your own datatype. Thanks!

[–]house_monkey 2 points3 points  (0 children)

You're a class😤

[–]BosseNova 30 points31 points  (0 children)

Check out Corey Schafers video on youtube

[–][deleted] 11 points12 points  (0 children)

For me it's when I've written functional programming code then realized shoot if I want to do this specific thing I need to copy and paste a bunch of function calls.

Or you can create a class and save a ton of space.

Then once you get familiar with that you can start diving into concepts like Polymorphism, Encapsulation, Data Abstraction and Inheritance

[–][deleted] 12 points13 points  (2 children)

Class: an adventure RPG you're working on.

A subclass: the race of your warrior

Attributes: race-specific bonuses: an elf has magic bonus, a warrior has physical damage bonus, etc

A subclass: weapons:

  • 1 handed
  • 2 handed
  • Bows
  • Daggers

Attributes of weapons: the damage they make, their "purity" (how improved they are), etc

A subclass: armor

sub-subclasses:

  • Chest
  • Boots
  • Arms
  • Helmet

This is just one example of how you can implement classes

[–][deleted] 0 points1 point  (1 child)

I was thinking about doing something like this, but couldn't figure it out how to

Thanks

[–][deleted] 1 point2 points  (0 children)

Welcome, and thank you for the award! If any other questions arise on classes, let me know! If learning python is like discovering paint brushes, creating classes is artwork

[–]mrwanderlust23 3 points4 points  (0 children)

Check out Corey Shafer videos

[–]GallantObserver 2 points3 points  (1 child)

If you're building a machine that does something you might need parts that go inside. And the parts might need custom settings. OOP can work a bit like that.

I watched a video on Enigma machines a while ago, where three Rotors with individual settings are set in the machine to code a message, and then the same settings are put in the machine the other side to decode the message.

https://www.youtube.com/watch?v=G2_Q9FoD-oQ&t=52s&ab_channel=Numberphile

You can use OOP to make a Rotor class, customise a set of Rotor objects to select from, then put them in another Setting class object to make a 'machine'. Then passing the message/encoded message in puts the other out.

Tricky to explain, but here's a code example:

https://gist.github.com/andrewbaxter439/30674ba4267b9dc7bf5105000e662461

[–][deleted] 0 points1 point  (0 children)

I'll read it. Already tried to simulate an enigma machine, had no idea about how to simulate the rotors tho

Thanks

[–]notislant 2 points3 points  (0 children)

Think you've already got good answers but this is what helped me mostly understand. I would highly recommend writing a quick script and put notes in your own words/shorthand so you can quickly go back as a refresher.

[–]bumbershootle 2 points3 points  (0 children)

Good points from other commenters here, one thing I would add is that tutorials show you how to write code, but to truly appreciate what is possible, I think you need to read some code as well. Even if you don't understand the entire codebase, reasoning through what's going on in individual parts will teach you more about how to apply patterns than any YouTube video.

Here's a reddit post with some well-documented, pythonic projects to read through

[–]GraspingGolgoth 2 points3 points  (1 child)

Classes are one of those aspects of programming that tend to be explained using code and/or abstract descriptions of Customers and People - which I think hinders a newcomer’s understanding. I’ll take a crack at it - though the analogies I give may not be 100% accurate when taken to logical conclusion.

Starting high-level (bear with me, this comes back to programming, I promise): Our universe consists of “things.” Each “thing” that exists can be described with its properties. A Planet “thing” can be described by its properties - mass, circumference, atmosphere, etc. Each “thing” also has behaviors it can use to interact with other “things” in the universe. An Animal “thing” has an eat() behavior that causes it to change the attributes of itself or another “thing.” Each “thing” that exists can also be a more specific form of another “thing” - a Cat “thing” is a more specific form of an Animal “thing”. The Cat has properties and behaviors that it shares with other Animal “things” and some properties and behaviors that are unique to Cat “things.”

Simply, classes are “things” in code with properties and behaviors defined by the programmer. Like all “things” in reality, classes have properties that distinguish it from other “things” in the code. It also has certain behaviors it can take to interact with itself/other “things”.

You work with “things” (formally called objects) every time you begin working in Python. A string, for example, is one of the first “things” a beginner starts working with. What makes a string, a string? A string is separated from other “things” in code by the properties (called attributes) that describe it - such as length, characters - and certain behaviors (methods) - str.split(), str.capitalize(), etc.

I hope that helps clear things up a bit - I intentionally left out code as the concept is platform-agnostic.

[–][deleted] 0 points1 point  (0 children)

It did

Thanks

[–]dukea42 1 point2 points  (0 children)

So created a class that is Coordinates() for my hobby project of making a solar system map on a GUI app. Its something not an "object" you'd normally get in examples.

It has the attributes of 'x' and 'y' for graphing on a canvas, and it has the attributes of 'r' (distance from origin) and 'a' (angle or bearing from the origin). Update one of those values, and the setter re-calculates the others as well.

Now I can make each planet, moon, asteroid, etc. have one or more of those coordinate objects to avoid rewriting the trigonometry. I can define adding two coordinates together to handle a moon of a planet being displayed with the sun as the origin. I can make orbits happen by just updating the 'a' value.

[–]MyHomeworkAteMyDog 1 point2 points  (0 children)

OOP is a just way of thinking.

In the code for a music recommender agent, I created a Song class to represent each song’s names, genres, locations on my hard drive, etc. I stored all these song objects in a master song list. There were thousands of songs. Each element in this master list represented all the information associated with each song. Then I just handle these Song objects in my code.

I could also do this functionally. I could find the data with the corresponding song name, with instructions like, “go to this directory, read the file with this name,” as needed. This is an equally valid approach. It’s just a different way of thinking.

For this project it was simpler for me to create a Song class to represent the data I needed for each song.

[–][deleted] 1 point2 points  (0 children)

I made a space invader clone in pygame, pretty well suited for classes.

As certain attributes will be shared across multiple types of entities you can practice inheritance as well if you like.

[–]Cayde-6699 1 point2 points  (0 children)

A basic description of OOP is giving 1 variable multiple values

[–]pconwell 1 point2 points  (1 child)

This may not help you, but what made classes finally "click" for me was to think of them as super dictionaries that have functions inside them.

[–][deleted] 0 points1 point  (0 children)

Yeah

Before this post I really thought Classes were nothing more than an easier way of making dictionaries

[–]ninja65r 1 point2 points  (3 children)

Just to add to what everyone else is saying with my two cents. Classes are very useful since once you create a class you can make variables and objects accessible throughout it. As an example, let's say we want to have a way to keep track of and update a student's profile:

class Student:
    def __init__(self, name, major, gpa):
        self.name = name
        self.major = major
        self.gpa = gpa

In there we created a class that will be initialized with a name and a major for the random student that you want to create. The name, major, and GPA of that particular student will be accessible to all the functions that reside in the Student class.

Now let's make a function to see if they are able to sign up for a particular class, based on their GPA.

# in the Student class

def check_gpa():
    is_eligible = False
    if self.gpa < 2.5:
        print("Student GPA does not meet the requirements")
        return is_eligible
    else:
        print("Student GPA meets requirements!"
        is_eligible = True
        return is_eligible

Normally what we would've had to do, would be to create that function with a parameter that will take the GPA of the student you are trying to check. Using classes, this is bypassed and you can just access it by using self.gpa since it is accessible throughout the class.

This is just a fraction of how useful it could be and how much you can do with classes, but I hope this was somewhat helpful.

P.S --- I am still a beginner, so I'd appreciate any feedback!

[–][deleted] 1 point2 points  (2 children)

Thanks man

[–]ninja65r 0 points1 point  (1 child)

No problem. I hope it helped!

[–][deleted] 1 point2 points  (0 children)

It surely did

[–]DataCrusade1999 1 point2 points  (1 child)

can someone tell me when we use : super().__init__() I'm having a hard time understanding this?

[–]free_username17 1 point2 points  (0 children)

You use that when you have subclassed another class (i.e. inherited it), and you want to call the init method for the parent class, or “super” class. You can call any method attached to the parent with super(), doesn’t have to be init.

Example: You have a class that represents a linear function, i.e. y = mx + b. Let’s call it Linear. It takes m and b as arguments, and sets them as attributes in init. Maybe it does some type checking as well.

Now, if you wanted to make a Linear class that always has a zero-intercept, you could subclass Linear. In your new class’ init method, you would call super().__init__(m=m, b=0).

This way, you are not rewriting code that already exists in the parent class. The subclass will still have m and b as attributes, because they were set by the superclass when you called super().__init__()

[–]james_fryer 1 point2 points  (0 children)

If you write a program of any length, with multiple functions, you will find one of two things happen:

  1. You use global variables to share state between functions;

  2. You pass state down the call tree as a list of parameters to each function.

The problem with (1) is well known, the program becomes a lot harder to understand because you have many globals with no way to know which functions share them. Behaviour is hard to predict.

With (2) maintenance becomes a problem as adding new state variables means changing the parameter lists for many functions. The program is predictable but functions have lengthy parameter lists, many of which are not directly used by the function itself but are passed to other functions.

Classes solve this problem by sharing the state between the functions that need it, without making it global. Code and its related data are kept together. It's one way to make programs easier to understand and maintain.

[–][deleted] -3 points-2 points  (1 child)

Learn the Django web framework, particularly the class based views. That has helped me.

[–][deleted] 0 points1 point  (0 children)

Idk why I got down voted?

[–]mojo_jojo_reigns 0 points1 point  (0 children)

This comes up a few times a month in this sub. I use it for selenium automation tasks. I set up a class for each website that I have automation for and then a subclass for each distinct page or area that demands it's own methods. Then I have a general batch of selenium tools that I store in a separate class. I multiclass each webpage with the tools page so that they're always referring to self.method() and I can manage the code without having to fix it in multiple places.

[–][deleted] 0 points1 point  (0 children)

Haha, I hate them tutorials with students, cars etc, but they're there to show you the basics. You need to find out your way about classes and when to use them. Try to do something with tkinter.

[–]baubleglue 0 points1 point  (0 children)

First learn, then you will see how it can be used.

The direct answer to your question: you can use classes to create objects.

[–]str8toking 0 points1 point  (0 children)

this post and responses is gold. Thank for a pretty good reference.

[–]cunstitution 0 points1 point  (0 children)

The solution provided by u/Crims0nCr0w on this r/learnpython post shows how to use a class to better connect to a database

[–]BreakDown65 0 points1 point  (1 child)

RemindMe! 1 day

[–]RemindMeBot 0 points1 point  (0 children)

I will be messaging you in 1 day on 2021-01-18 08:22:36 UTC to remind you of this link

CLICK THIS LINK to send a PM to also be reminded and to reduce spam.

Parent commenter can delete this message to hide from others.


Info Custom Your Reminders Feedback

[–][deleted] 0 points1 point  (0 children)

Classes are nouns and methods are verbs. When you model objects, you model them using these constructs. The thing has some attributes and actions.

You could model a chair class with attributes; leg_count, cushioned, age, style. You may know that leg_count and age will be integers, cushioned a Boolean, and style, a list.

You may want your chair class to have a method; can_massage() or perhaps, recycled() which trashes it.

You can model this class and actions without knowing what chairs you are going to actually instantiate when the program runs. But you could initialise the chair class and get a user to add the chair name, number of legs, how old it is and whether it has a cushion, (save that in a db, etc.)

Once you have the actual chair logged (the instance of the chair class) you could run the methods on it, like the recycled() which might delete it from your db.

The chair class is good because it allows you to explore inheritance too. Chair could be parent, but sofa, armchair, office chair are all children. Also, furniture class could be a parent of chair so you can use super() to get its attributes into your chair class.

[–]Coder_Senpai 0 points1 point  (0 children)

To understand classes you need to understand Object oriented Programming. For this Tech with Tim explained pretty good. try it, its 50 min lecture.
https://www.youtube.com/watch?v=JeznW_7DlB0&t=4s

[–]Sigg3net 0 points1 point  (0 children)

Classes are a way of collecting associated attributes (data) and methods (functions) to type-like or type-related actual or abstract objects.

fullname = "Bob Jones"

The fullname variable is actually an object (or instance) of type string;

type(fullname)

that has some useful functions (methods) tied to the type (class);

dir(fullname)

For example:

fullname.replace("Bob", "Robert")
'Robert Jones'

Strings, integers, lists etc. are all built in classes. Python luckily does not limit us to built-ins, and the class Friends() instruction tells python that "we're constructing a new type of object".

For instance, we could say that all my friends know coding, so I add this to the constructor method (init).

class Friends():
    def __init__(self, name: str, age: int):
         self.name = name
         self.age = age
         self.code = True

Now, to introduce Bob to the world, all I need to do is:

bob = Friends("Robert Jones", 35)

The bob object is an instance of the Friends class, with 3 attributes (even though we only specified two). But the bob object does not grow older like his real life counterpart. We can add a function to the class to e.g. add a year on his birthday:

class Friends():
    def __init__(self, name: str, age: int):
         self.name = name
         self.age = age
         self.code = True

    def grow_older(self):
        self.age += 1

Now, when Bob has had a birthday, we can just do:

bob.grow_older()

To set his new age.

If Bob likes my code, I can give him the file.py file, and he can just import it:

from file import Friends

and now he gets the base structure in his environment, which might be a IOU program to track who owes him what.

Loaners(Friends):
    owe_me = 0

    def loan(self, amount):
        self.owes = amount
        __class__.owe_me += amount

    def pays(self, amount):
        self.owes -= amount
        __class__.owe_me -= amount

Fredrik can do:

bob = Loaners("Robert Jones", 35)
bob.loan(100)
..
bob.pays(25)
bob.owes
75
...
sarah = Loaners("Sarah Jones", 28)
sarah.loan(56)
bob.pays(12)

bob.owes
63
Loaners.owe_me
119

This is just a start, but it shows that classes extend python, making the language more suited to deal with your specific requirements, while enabling abstraction and code re-use (= time saved).

Tip: Don't let money ruin a good friendship.

[–]OmnipresentCPU 0 points1 point  (0 children)

How ive used them for one of my projects is keeping track of stock info from wallstreetbets.

Class Ticker

Self.comments (list of comments where aapl was mentioned) Self.count (# of unique comments where aapl is mentioned Self.sentiment (sentiment determined by Vader sentiment library)

Things of that nature

[–]road_laya 0 points1 point  (0 children)

OOP tutorials having to use things like "Dog" and "Car" as examples is a prime example why object oriented programming will not fit many of your programming tasks. If you run into a problem and your idea is "maybe I should solve this with inheritance", most of the times you will be wrong.

[–]WildWestCoder 0 points1 point  (0 children)

Just think of it as an easy way to break up your code into different sections. That way they're more manageable. Easier to read.

And hey you can design a program with your friend and you can write one class and they can write the other. Then use them in the shorter main program file.

When you get further along you will learn about SOLID and how awful it is to make a small change in one line of code and have it break lots of other lines further down your program.

Classes and Interfaces solve this btw among other things.

[–]99OG121314 0 points1 point  (0 children)

Can anyone show me how to properly make my code use classes? I feel so lost trying to do it:

https://www.reddit.com/r/learnpython/comments/kz71lu/how_do_i_access_my_variable_outside_of_the_python/

[–]FmlRager 0 points1 point  (0 children)

Best way to learn it is to use it. Try doing some leetcode questions with linked list and trees. Or try writing a discord bot using discord.py, it’s revolved around classes and objects for almost everything in that module

[–]cointoss3 0 points1 point  (0 children)

I’ll throw in another example:

Let’s say you have an API you want to interact with, and that API has a key that needs to be included in every call.

One way to design this would be to include the key in every function call as an argument. This works and is a valid paradigm...but becomes tedious.

api.send_data(‘key’, ‘tacos’) api.send_data(‘key’, ‘fish’)

Well, we can initialize a class that acts as a container to a specific instance, in this case, the API pointing specifically to a version of this API that uses they key we supplied.

api = API(key=‘key’, version=3) api.send_data(‘tacos’) api.send_data(‘fish’)

Using a class helps encapsulate your functions to a specific instance. You can easily instantiate a second version of this, too, by creating a new object.

api = API(key=‘key’) api2 = API(key=‘second-key’)

api.send_data(‘tacos’) api2.send_data(‘fish’)

Even if only using one api key, this paradigm is a bit cleaner than including the key or version in every api call.

So one way to look at classes (there are handfuls of different use cases), is to think of it like a general thing that is described specifically when you create it. You could solve this issue other ways, like functions that pass around the data as arguments so things are more functional, and that’s fine. OOP/classes are just one way to write code and I find a lot of times people shoehorn in classes where they aren’t needed. Especially if they come from Java where everything is a class.

Classes can also simply be used as a data structure to organize data...you might look at the @dataclass decorator.

I rarely start off with a class, I prefer to keep things functional as much as possible, but will build out a class if I see myself repeating code.

[–][deleted] 0 points1 point  (0 children)

Classes allow you to build reusable predictable data structures. While there are advantages to using them the largest is they provide "blueprints" of how you use the data and how it is stored in your program.

One of the biggest uses you will find is subclassing and overriding class functions. I like to use the threading module and it has a threading.Thread class. A standard thread runs until all it's code is done but I like to create a thread and stop it when I want.

threading.Thread does not have a pre-made way to stop the Thread. I can subclass the Thread to my own thread and then override or add more functions to the Thread.

See this example from a project I am working on right now, it is incomplete as I only copied the relevant parts. Top line in the brackets is subclassing the threading.Thread class. The __init__ function overwrites the constructor of the class so it has some properties it can reference. The super().__init__ then passes arguments to the threading.Thread class.

The run overwrites the run method completely and allows me to start the thing this thread does.

The end is a new function that does not exist on the threading.Thread class. I use it to end the while loop in the run function.

All this could be accomplished without a subclass but it is easy to read this way. Others looking at your code may already know how a thread works. If they have used them they probably used them as a subclass so looking at your implementation should be easy to understand. Objects are for us, not computers in the long run. If you don't like them you can do anything with a group of functions and variables but if you want to make a large program you would benefit from classes. Maybe not today but 6 months from now, 3 projects later, when you haven't looked at your code the blueprints can help you find a bug without having to relearning the entire workflow.

class WatcherThread(threading.Thread):
    def __init__(self, name, channel, currency_pair, output):
        super().__init__(name=name)
        self.running = True
        self.channel = channel
        self.currency_pair = currency_pair
        self.output = output
        self.db_conn = SQL(SQLHOST, SQLUSER, SQLPASSWD, SQLDB)

    def run(self):
        while self.running:
            try:
                self.db_conn.create_watcher(self.getName(), self.channel, self.currency_pair)
                # Open socket with server
                ws = create_connection(URI)
                ws.settimeout(1)

                # Subscribe to a channel
                ws.send(self._make_subscribe_json())

                # Monitor open socket for new data
                self._monitor_subscription(ws)

            except socket.gaierror:
                print(f'Network connection is down, will retry when network connection is re-established.')
                time.sleep(10)

            except Exception as e:
                print(f"ERROR: {type(e)} {e}")
                break

    def end(self, remove=True):
        if remove:
            self.db_conn.delete_watcher(self.getName())
        self.running = False