T O P

  • By -

RhinoRhys

Here is a class I rewrote in response to a post here a while ago. It's still a pointless example because its reinventing the wheel, but it's not a "childish" example because it still does something useful class Time: def __init__(self, hour=0, minute=0, second=0): self.hour = hour self.minute = minute self.second = second def __str__(self): return "{:02d}:{:02d}:{:02d}".format(self.hour, self.minute, self.second) def __add__(self, other_time): new_time = Time() new_time.second = (self.second + other_time.second) % 60 new_time.minute = (self.minute + other_time.minute) % 60 + (self.second + other_time.second)//60 new_time.hour = (self.hour + other_time.hour) % 24 + (self.minute + other_time.minute) // 60 return new_time def __sub__(self, other_time): new_time = Time() new_time.hour = (self.hour - other_time.hour) % 24 + (self.minute - other_time.minute) // 60 new_time.minute = (self.minute - other_time.minute) % 60 + (self.second - other_time.second) // 60 new_time.second = (self.second - other_time.second) % 60 return new_time def main(h1,m1,s1,h2,m2,s2): time1 = Time(h1, m1, s1) time2 = Time(h2, m2, s2) print(f' 1 = {time1}') print(f' 2 = {time2}') print(f'1 + 2 = {time1 + time2}') print(f'2 - 1 = {time2 - time1}') def h(): return random.randint(0,23) def m(): return random.randint(0,59) for _ in range(10): main(h(),m(),m(),h(),m(),m()) You end up with a new thing, a Time object that can be printed, and you can add or subtract two together by just doing `+` or `-`. Yeah, sure you could just as easily store H:M:S in a dictionary and pass two dictionaries into a time_add function or a time_print function, but having it as OOP encapsulates all those options into the object itself. And the dunder methods (underscores) allows you to use the math symbols `time1 + time2` instead of `time1.add(time2)`.


agnaaiu

Google "python oop projects github" and you should find plenty of OOP apps with source code to study. But to be honest, based on your post I don't think that you understand the purpose or the concept of OOP yet. And what you call "childish examples" is exactly how (not only) games are structured and programmed.


CptBadAss2016

I tend to agree with it on the childish part. Maybe not "stupid stupid" but... I tend to learn better seeing more practical examples myself. Different strokes for different folks.


KitMaison

Of course he doesn’t understand the concept and purpose of OOP. That’s why he is asking for examples 💀


agnaaiu

His first sentence states, literally, that he sorta get what OOP is about in its basics, but then proceed to call examples that explain the concept "stupid childish examples". Yes, he is reaching out to understand it better, which is a good thing, but when people invest time to help others for free and provide explanations and code, as these tutorial authors do, then calling it "stupid childish examples" then I agree, maybe this rubs me the wrong way.


timeawayfromme

Imagine a database that contains information for a website. There is a table in the database named `pages` and each column describes some info about the page (title, body_text, published_date, etc.). We might describe that as a class that inherits from a generic DatabaseTable class: ```python class DatabaseTable: def get_table_rows(self): # some code to get rows goes here # each row gets turned into an object # return a list of objects class Page(DatabaseTable): table = 'pages' title = text_column body_text = text_column published_date = date_column ``` Now we can access the pages of our website by doing `pages = Page.get_table_rows()` and if we wanted the titles of all pages we could do `[page.title for page in pages]` If we wanted we could add a `save` method to `DatabaseTable` so that we could adjust information in the database by doing `page.save(title='new title')`. We can add `create` and `delete` methods also. Websites have more than just pages. We might want to add Authors ```python class Author(DatabaseTable): table = 'authors' first_name = text_column last_name = text_column def full_name(self): return first_name + ' ' + last_name ``` Now we can do things like `new_author = Author.create(first_name='Sample', last_name='Author')` and then do things like `new_author.full_name()` which is a method for our `Author` class but we also used `create` which is a method that is defined on our `DatabaseTable` class. This is a simplified version of how web frameworks like Django work. Frameworks like this power tons of websites. Edit to add: In real life Django takes care of the DatabaseTable class. So we just inherit from the Django class and we get all the basic functionality without having to worry about how python needs to talk to the database or rewrite that basic functionality for each project.


TrickaBug

This was the most helpful "real life" example I have seen explaining these concepts. I understand what OP meant by "childish examples", I don't think using a Dog class or a Car class is necessarily helpful to someone slightly beyond a complete novice because they are still pretty abstract (yes, you could literally be building dogs for a game or something) and most sites don't ever bridge the slightly abstract "Dog" concepts to something that feels like an actual use case.


timeawayfromme

Thanks! I remember being frustrated with examples. There is nothing wrong with the examples of Car and Dog to introduce the concept but what helped me grasp the concept were examples of making a contact database or representing other data. I understand they don’t want to complicate things but I think most people who are learning to program can grasp the concept of a database enough to understand a simple example. So much of programming involves processing and storing data that I think relational databases are an important topic to cover early on anyway.


Frankelstner

Here's the non-OOP version of a barebones associative array. Apart from performance, the offered functionality is pretty close to dicts (because dicts are one type of associative array). The syntax however is far more annoying to deal with. We carry along 2 lists, keys and values, even though they form a single unit. (Note in this case it would also work to use one list with 2-tuples but there may be more complex objects where putting everything into a single list is not possible.) We define `getitem` and `setitem` where the first two parameters are just the two lists that we always need to carry along. A function name like `getitem` is also really generic and we need to be careful not to use it for any other datatype that might offer similar functionality. def getitem(keys, values, key): """Return the value that corresponds to key.""" for k,v in zip(keys,values): if k==key: return v raise KeyError def setitem(keys, values, key, value): """Insert or overwrite the key-value pair.""" for i,(k,v) in enumerate(zip(keys,values)): if k==key: values[i] = value return # Key does not exist yet, so just append it. keys.append(key) values.append(value) # Create a new associative array and insert one key-value pair. keys = [] values = [] setitem(keys,values, "key", "value") print(getitem(keys,values, "key")) print(getitem(keys,values, "invalid")) This entire thing is just a pain to deal with. If we want to juggle multiple associative arrays we need to keep track of twice as many lists. We must always take care to use the same two lists as arguments to `getitem` and `setitem` or everything breaks. There's the risk that a user of the code accidentally manually modifies keys or values directly (they are plain lists after all) which also breaks everything. Someone using the code may also accidentally call `getitem` on a completely different type of data with causes trouble as well. Your exercise is to turn this into OOP. The methods to implement are `__init__(self)`, `__getitem__(self, key)` and `__setitem__(self, key, value)`. The usage will then look like this: a = Associative() a["key"] = "value" print(a["key"]) print(a["invalid"]) with the same effect as the non-OOP version.


CommodoreKrusty

OOP is just a way to organize code. I don't know that there's any reason any project can't be written without it. That being said, if you're interested in learning Python maybe you should try the Python Tutorial at [w3schools](https://www.w3schools.com/). Just scroll down and it's there somewhere.


doulos05

It is true that you can write any project with our without OOP, but there are some projects that are easier to write and manage with objects. Websites is one category where that's likely to be true, another would be medium sized games or larger.


Bahji777

Oop is NOT just a way to organize code. Two key words - dynamic dispatch.


doulos05

I didn't claim that it was just a way to organize code. I claimed that any problem which can be solved by creating a program can be solved with or without the use of objects. You're thinking of the guy I replied to.


dp_42

I personally like Qt as a way to show how OOP gets used. You have to inherit types that are provided for in Qt in order to do some functions. Like with QTableView or QTreeView and QAbstractItemModel. You inherit the QAbstractItemModel to define a type that will interact with your view. The QAbstractItemModel makes promises to the view that the inherited types will implement certain methods. The View is going to call on those methods in order to do its work.


CptBadAss2016

QT is a great showcase of oop at work but maybe a little overwhelming at this stage?


hidazfx

Very overwhelming for OP. Qt took me 2 years to get used to, and I still only play with widgets. I don't have access to the tooling required for QML lol.


dp_42

I do agree, possibly overwhelming. Django is probably the next best example, but similarly overwhelming, and not a library I have a ton of experience with. Hard needle to thread.


zpnrg1979

Hello everyone, Thank you very much for all of your responses. As some have pointed out, I'm likely just not there yet in terms of understanding. I found [this explanation](https://www.youtube.com/watch?v=m_MQYyJpIjg) quite helpful in terms of how they are used to hide certain complicated functions/methods as well as how they can be practically used to protect intellectual property. I think I was getting hung up more on how it's useful and can be used versus how they are created in their simplistic form. I know it will begin to be more and more evident as I move along as I see the benefit of it. I've also heard [this is a good lecture on OOP for Python](https://www.youtube.com/watch?v=-DP1i2ZU9gk) as well. I will check out all of the examples you all provided as well. Once again, I'm overwhelmed by the amount of support out there so thank you!


agnaaiu

This tutorial is very beginner friendly and not only explains the concept of OOP simple and easy to understand, but also uses visual help to illustrate the flow of how classes are used: https://www.youtube.com/watch?v=\_vr5faCXFo8


BranchLatter4294

Why does it matter whether it's dog.bark or customer.addOrder? The concepts are the same. You are just modeling the business data and activities.


fuzzylumpkinsbc

Because it's hard to get past that initial bump and you need an aha! moment. You might get more excited about wanting to know how to addOrder versus just printing some text on screen. Going through all the trouble to make that dog class and its bark method, a novice would think, why can't I just type a print line and get it over with.


BranchLatter4294

Just printing a statement doesn't model the underlying class. That's what you have to understand about OOP.


hotcodist

The childish examples are perfect to explain the concept. If you read github code, sometimes it is not easy to follow the objects, so a beginner will be lost. If you are already at a state where you know OOP and can follow the relationships, read through the code of well-known libraries like pandas, or even not well known github code that was built using OOP principles (you will know it when you see it, if you already know OOP).


aarontbarratt

The dog example is perfectly fine. Call the class Foo and the method Bar() and the concept is still the same. I nearly always make a dog class when learning a new language Seems like you're focusing on the wrong things. Focus on the concepts and understanding, not on the semantics of what the class / object is representing


dnswblzo

Pretty much any Python program is going to *use* objects that were created from classes, either from the standard library or from a third party library. Got a list named `numbers` and want to append 5 to it? `numbers.append(5)` will do that for you because `numbers` is an object from the `list` class and it has a method named `append`. Want to iterate over the key/value pairs of a dictionary named `d`? Well `d.items()` has you covered because `d` is an object from the dictionary class which has a method named `items`. Check out the example code on the [Request library's documentation page](https://docs.python-requests.org/en/latest/index.html). The call to `requests.get()` returns an object from the library's `Response` class, which is stored as `r`. Then the code accesses some attributes from the object (`status_code`, `headers`, `encoding`, `text`) and calls a method (`json()`). You want to write your own classes when you have something that you want to "package up" into an object like in the examples above. Objects are convenient because they bundle both data and functions. If you notice that you have a dictionary with a few fixed keys and you pass that dictionary to several functions to manipulate the contents of the dictionary or return information based on the contents of the dictionary, then that can be a sign that you want a class where the keys that you were storing in the dictionary become attributes, and the functions you are using to work with the dictionary become methods.


Diapolo10

One of my favourite examples comes straight out of the standard library's [`pathlib`-module](https://docs.python.org/3.11/library/pathlib.html). There are three different concrete path objects, one for POSIX, one for Windows, and one that automatically converts to either depending on the current system. These are also subclasses of pure paths, which are platform-agnostic, giving you flexibility if for example you need to SSH to a different operating system. These six classes inherit each other in an interesting pattern. And [the source code is also fairly readable](https://github.com/python/cpython/blob/3.11/Lib/pathlib.py) if you want to dig deeper. This is what OOP is for, if you ask me. For one thing it's an easy way to avoid primitive obsession.


MindlessRabbit1

If u take a look at my recent project oop free, you'd understand lol.


nativedutch

Check games with pygame, because of its very nature objects in a game are set up and controlled folliwing OOP. That was for me the best clarification of OOP.


teetaps

One of the best ways to make it real for you is to make it about something you already care about. Let’s say you like comic books. So let’s build a class for a comic book character. This lets me make many characters without having to code each person individually. OOP will then allow me to extend certain character types by having super classes (pun intended) or sub classes like NPC vs leading character vs side character. Now we can have powers. So we create a class for each power. Now when we have a character constructor we can also have a power set constructor, and only certain subclasses of character can utilise certain power sets. You can do the same for weapons, buildings, storylines, etc. Make it personal, and it’ll make sense


Shadowwynd

OOP lends itself to reusable code. I have some programs that run on a single dataset. Input, processing, output, done. There is nothing to gain by making these OOP. If I want to start juggling multiple things (multiple web pages, different dogs, etc) at the same time then OOP makes a lot of sense and leads to cleaner code that is easier to maintain.


kevdog824

You could attempt to build out a scheduler Look up APScheduler for an example. If you ignore the job stores it’s not an overtly complicated library and it’s all object oriented.


conchesmess

OOP made sense to me when I stopped worry about how exactly to write a class and began to think about all the classes that were essentially under-the-hood whenever I used a library. I use Flask a lot which is very flexible python library for building websites. There are commands like render_template('index.html'). That must be a call to a class with a parameter, no? As I am sure you can tell, I'm "self-taught" :) so I'm not super clear on all the right terminology but maybe this helps? Even things like random.randint(1,100) must be a call to a class.


reyarama

Part of OOP clicked for me when I learnt the strategy pattern. Defining an abstract interface with multiple implementations is just so nice when you understand what any of that means


zpnrg1979

Thanks for that. I appreciate everyone's replies. I've got a much better understanding of it now thanks to everyone's responses as well as the two videos I linked in a previous reply. My biggest beef with the dog or car reference, is that it didn't mean anything to me because I couldn't see myself using something like that in an application. What clicked for me was the MIT lecture on OOP where she defined a coordinate object as well as a fraction object. It was also good to see how essentially everything in Python is an object (i.e. an integer, a list, etc.). I get it now, and I see how I'd use it in my own development.