5 Intro to OOP
Class
Defining a class creates a new datatype. An object is an instance of a class (everything in python).
Attributes
An object whose datatype is of our class is called an instance of a class. For example 3 is an instance of the class int.
Each instance can hold more than just a singe piece of data, each of these pieces is called an instance attribute. You can think of this as nouns that describe the object.
Example of a Tweet as a class.
from datetime import date
class Tweet:
""""A tweet, like in Twitter.
=== Attributes ===
userid: the id of the user who wrote the tweet.
created_at: the date the tweet was written.
content: the contents of the tweet.
likes: the number of likes this tweet has received.
"""
# Attribute types, do not create instance variable and could be removed but is good practice and understood by automated tools
# client code
userid: str
created_at: date
content: str
likes: int
def __init__(self, who: str, when: date, what: str) -> None:
self.userid = who
self.created_at = when
self.content = what
self.likes = 0
*putting a _ in front of an attribute makes it "private"
Creating an instance: tweet = Tweet()
But in order to create and initialize instance attributes for a class we need to use the method __init__
self
automatically receives the id of the instance that is to be initialized.
>>> t1 = Tweet('Giovanna', date(2022, 1, 18), 'Hello')

and after the return Tweet.__init__
we have:

we can access the attributes by using dot notation like t1.created_at
Methods
Functions inside the class, like the verbs related to the object. The benefit is that unlike a function, it doesn't require imports like a regular function; it is already associated with the class.
class Tweet:
...
def like(self, n: int) -> None:
"""Record the fact that <self> received <n> likes.
Precondition: n >= 0
"""
self.likes += n
tweet.like(10)
dot notation already passes self.
Can be called two ways, for example for strings
word = 'supercalifragilisticexpealidocious'
word.count('i')
# or
str.count(word, 'i')
Special Methods
Representation Invariants
Making sure that rules are consistent and documented. A representation invariant is a property of the instance attributes that every instance of a class must satisfy. There are documented in the doctring.
Documentation:
class Tweet:
"""A tweet, like in Twitter.
=== Attributes ===
userid: the id of the user who wrote the tweet.
created_at: the date the tweet was written.
content: the contents of the tweet.
likes: the number of likes this tweet has received.
=== Representation Invariants ===
- len(self.content) <= 280
"""
# Attribute types
userid: str
created_at: date
content: str
likes: int
Enforcement
Assume that all representation invariants are satisfied but also make sure that at the end of the method it is still satisfied. So it is a precondition and a postcondition. However, you can temporarily violate it in the body of the code.
You can use initializer arguments to further enforce like:
def __init__(self, who: str, when: date, what: str) -> None:
"""Initialize a new Tweet.
If <what> is longer than 280 chars, only first 280 chars are stored.
Precondition: len(what)<= 280 # here is one option ************
>>> t = Tweet('Rukhsana', date(2017, 9, 16), 'Hey!')
>>> t.userid
'Rukhsana'
>>> t.created_at
datetime.date(2017, 9, 16)
>>> t.content
'Hey!'
>>> t.likes
0
"""
self.userid = who
self.created_at = when
self.content = what[:280] # or here ************
self.likes = 0
However nothing fully prevents client code from violating representation invariants.
Designing Classes
Thus far there are 3 elements:
- instance attributes (data)
- methods (operations)
- representation invariants (properties)
Design Recipe:
link
Main themes are, design before coding and information hiding (separation from the public interface).
Private-ness:
In python naming convention, anything considered private starts with a leading underscore. The client should not access or change the value. Python has a "we're all adults philosophy" so unlike other languages, editing the variable might not raise an error.
Class Composition
It's common for an instance of a class to have and attribute that refers to another class. For example, in Twitter, there may be a user class and a tweet class.