Class Attributes

Learn the difference between instance attributes and class attributes.

Great work so far!

Our users can now create and interact with posts effortlessly, but there’s a key issue we need to address: tracking the total number of posts and users. Currently, while we’ve created User and Post objects, each of these objects is self-contained. This means that they don’t share statistical information across all instances, and we have no easy way to know how many posts have been made or how many users have joined the platform.

The problem is that there is no centralized way to share this kind of information across instances.

But before that, we need our code to look better, be easier to read, and be easy to understand. Let's do that!

Organizing our project

So far, we’ve written all our code in one file. While that’s perfect for learning small examples, real-world projects benefit greatly from a modular design. Organizing your code into separate files has several advantages:

  • Maintainability: Each class lives in its own file, making it easier to locate, modify, and debug code.

  • Reusability: Modules can be imported into other projects.

  • Collaboration: In larger teams, different developers can work on different modules simultaneously.

  • Organization: A clean file structure helps you manage and scale your project.

Now, let’s see how we can structure our Chirpy project.

chirpy/
├── user.py # Contains the User class
├── post.py # Contains the Post class
└── main.py # Main file to run the application
File structure for chirpy

Let’s implement this structure!

from post import Post  # Import the Post class

class User:
    def __init__(self, username, display_name):
        self.username = username
        self.display_name = display_name

    def show_profile(self):
        print("User:", self.display_name, "(@" + self.username + ")")
    
    # Instance method to create a post
    def create_post(self, content):
        # Here, the user itself is the author of the post
        post = Post(content, self)
        return post

    # Optional: Instance method to like a post
    def like_post(self, post):
        # This calls the post's like_post method, passing self as the user
        post.like_post(self)
Project organization in seperate files

In the above code, the only new difference is imports. If we want to use any other class inside a class we just have to import it at the top of that class. For example, we needed both User and Post class in the main class so we imported both classes at the top. The rest is the same. ...