Objects and Classes¶

In this lesson, we'll practice type annotations and class-building to create some Ed posts!

In [1]:
!pip install -q nb_mypy
%reload_ext nb_mypy
%nb_mypy mypy-options --strict
[notice] A new release of pip is available: 25.0.1 -> 25.1.1
[notice] To update, run: pip install --upgrade pip
Version 1.0.5

Group Activity: Ed Posting¶

Define a class EdPost that represents a question on the discussion board. The EdPost class should have an initializer that takes an argument for each of the 4 fields your class should have. Each field should use the same names as its parameter, except that it needs to be declared private.

  • The bool flag that marks the post as private or public. This field does not have a default value. If True, then the post is public. If False, then the post is private.
  • The str title of the post. This field does not have a default value.
  • The str tag of the post. If the parameter is not given, the tag field should be 'General'.
  • The list[str] comments on the post. If the parameter is not given, the comments field should be [].

Your class should have the following methods.

  • An initializer that takes the parameters to initialize the fields as described above (in that order).
  • A method get_title that returns the title of the post.
  • A method get_tag that returns the tag on the post
  • A method add_comment that adds a comment (str) to this post.
  • A method display that prints out information about the post the following format, replacing the uppercase placeholders for TITLE, TAG, COMMENT, and ... accordingly. The comments should appear in the order they were added, one on each line and indented by two spaces.
TITLE (TAG)
Comments:
  COMMENT
  COMMENT
  COMMENT
  ...

If the post is private, then the display method should only print "Private post!" instead (with no comment or tag information).

Here's an example call:

post1 = EdPost(True, "Typo in spec?", "Education")
post1.add_comment("There was a typo!")
post1.add_comment("And maybe another typo?")

post2 = EdPost(True, "What's Wen's favorite cat?")
post2.add_comment("There can't be just one!")

post3 = EdPost(False, "I need help!", "Processing")

post1.display()
print()
post2.display()
print()
post3.display()

And its output:

Typo in spec? (Education)
Comments:
  There was a typo!
  And maybe another typo?

What's Wen's favorite cat? (General)
Comments:
  There can't be just one!

Private post!
In [2]:
class EdPost:
    def __init__(self, is_public: bool, title: str, tag: str = 'General',
                 comments: list[str] | None = None) -> None:
        self._is_public = is_public
        self._title = title
        self._tag = tag
        if comments is None:
            self._comments = []
        else:
            self._comments = comments

    def get_title(self) -> str:
        return self._title

    def get_tag(self) -> str:
        return self._tag

    def add_comment(self, comment: str) -> None:
        self._comments.append(comment)

    def display(self) -> None:
        if self._is_public:
            print(f'{self._title} ({self._tag})')
            print('Comments:')
            for comment in self._comments:
                print('  ' + comment)
        else:
            print("Private post!")
In [3]:
post1 = EdPost(True, 'Typo in spec?', 'Assignment 1')
post1.add_comment('There was a typo!')
post1.add_comment('And maybe another typo?')

post2 = EdPost(True, "What's Wen's favorite cat?")
post2.add_comment("There can't be just one!")

post3 = EdPost(False, "I need help!", "Processing")
post3.add_comment("TA response")

post1.display()
print()
post2.display()
print()
post3.display()
Typo in spec? (Assignment 1)
Comments:
  There was a typo!
  And maybe another typo?

What's Wen's favorite cat? (General)
Comments:
  There can't be just one!

Private post!

Whole Class Activity¶

Uh-oh, looks like we forgot a very important feature of Ed posts-- their authors! Let's make an AuthoredEdPost class to take in a string author parameter (if none is provided, the author should be "Anonymous"). Authors can write Ed posts, but they can also add comments! All methods in the AuthoredEdPost class are the same as those in the EdPost class, with some excpetions. Do the following tasks in the AuthoredEdPost class:

  • Add the author parameter to the initializer. If no author is provided, default to "Anonymous". This parameter should be a string.
  • Add a method get_author() that returns the author of a post.
  • Add a method get_commenters() that returns a dictionary where the keys represent the authors of comments and the values are a list of that author's comments. (Hint: you may need to create a new field to help with this!)
  • Update the add_comment() method so that you are keeping track of the author of each comment in addition to the comment itself. If there is no author given, default to "Anonymous".
  • Change the display method so that it aligns with the following format:
TITLE (TAG) by AUTHOR
Comments:
  COMMENT_AUTHOR: COMMENT
  COMMENT_AUTHOR: COMMENT
  COMMENT_AUTHOR: COMMENT
  ...

AUTHOR is the author of the EdPost, while each COMMENT_AUTHOR is the author of their respective comment.

In [4]:
class AuthoredEdPost:
    def __init__(self, is_public: bool, title: str, tag: str = 'General',
                 comments: list[str] | None = None, author: str = 'Anonymous') -> None:
        self._is_public = is_public
        self._title = title
        self._tag = tag
        if comments is None:
            self._comments = []
        else:
            self._comments = comments

        # adding author and commenter fields
        self._author = author
        self._commenters: dict[str, list[str]] = {}

    def get_title(self) -> str:
        return self._title

    def get_tag(self) -> str:
        return self._tag

    # add getter method for the author
    def get_author(self) -> str:
        return self._author

    # add getter method for the commenters
    def get_commenters(self) -> dict[str, list[str]]:
        return self._commenters

    def add_comment(self, comment: str, author: str = 'Anonymous') -> None:
        self._comments.append(comment)

        # Add to the commenters dictionary
        if author not in self._commenters:
            self._commenters[author] = [comment]
        else:
            self._commenters[author].append(comment)

    def display(self) -> None:
        if self._is_public:
            # Update the format of the display to show the authors of comments and posts
            print(f'{self._title} ({self._tag}) by {self._author}')
            print('Comments:')
            for author, comment_list in self._commenters.items():
                for comment in comment_list:
                    print('  ' + author + ": " + comment)
        else:
            print("Private post!")

Now, let's mess around with authored Ed posts!

In [5]:
post3 = AuthoredEdPost(True, "Who's the best superhero?", "Social")
post3.add_comment("Superman!")
post3.add_comment("Clearly it's Batman", "Vatsal")
post3.add_comment("Any X-men fans?", "Suh Young")

post4 = AuthoredEdPost(True, "Does Kevin like cats?")
post4.add_comment("No comment", "Kevin")

post3.display()
print()
post4.display()
Who's the best superhero? (Social) by Anonymous
Comments:
  Anonymous: Superman!
  Vatsal: Clearly it's Batman
  Suh Young: Any X-men fans?

Does Kevin like cats? (General) by Anonymous
Comments:
  Kevin: No comment
In [ ]: