Classes
Contents
Classes#
Goals of this lecture#
This lecture will cover classes in Python.
While there’s not enough time to discuss classes in detail, we’ll focus on the following topics:
- What is a class? What is it useful for? 
- How do you define a class in Python? 
- Practical: how do you find out information about a - class?
What is a class?#
A Python
classdefines an object. Each object is a way to organize data (attributes) and operations to perform on that data (methods).
We’ve encountered objects before.
- A - listis a type of object, which has associated methods:- append,- pop, and more.
 
- A - dictis also a type of object.- update,- keys,- items, and more.
 
- So are different types of data ( - bool, etc.) and even- functions.
What makes objects useful?#
Objects are useful for organizing data and operations in a structured way.
- Example: consider representing the date. 
- Format is MM/DD/YYYY: 09/18/2022 
Using a str#
We could represent the date with a str, but it’s hard to perform operations with this representation. (E.g., what if we wanted to compare this date to another date?)
## Representing as a string
date_str = "09/18/2022"
date_str
'09/18/2022'
Using a list#
We could represent the date with a list, but then we’d have to remember which index corresponds to each feature.
## Each index corresponds to MM, DD, and YYYY
date_list = ['09', '18', '2022']
date_list
['09', '18', '2022']
Using a dict#
We could also represent the date with a dict, which adds more structure.
## Now each *key* tells us more about what a given value reflects.
date_dictionary = {'day': 18,
                  'month': 9,
                  'year': 2022}
date_dictionary
{'day': 18, 'month': 9, 'year': 2022}
Using datetime#
But we could also use a Python object that’s engineered to represent the date specifically.
## This is called an import statement
## We're *importing* a useful package to use
from datetime import date
date_object = date(day = 18,
                  month = 9,
                  year = 2022)
date_object
datetime.date(2022, 9, 18)
Classes can unlock more affordances#
Because the date object is built specifically to represent dates, it has many custom methods we can use to perform operations on those dates.
## Retrieve day information
date_object.day
18
## Convert to calendar time
date_object.ctime()
'Sun Sep 18 00:00:00 2022'
Comparing dates!#
Having a custom object makes certain operations much easier, like comparing dates.
date2 = date(day = 17, month = 9,
            year = 2022)
## How far apart are these dates?
date_object - date2
datetime.timedelta(days=1)
Attributes vs. methods#
An attribute is data associated with an object. We can access attributes using the dot (object.attr_name) syntax.
date2.day
17
A method is a function that belongs to an object, and which operates on that object. We can access methods using the dot syntax as well (object.method_name()), but they also require parentheses (), since they are functions.
date2.ctime()
'Sat Sep 17 00:00:00 2022'
Summary: why classes?#
- Often, we need to work with a set of data and operations to perform on that data. 
- In theory, we can do that with a combination of - lists and- dictionaries.
- But a custom class makes things much easier. - Python has tons of custom objects, that make your life easier in this regard. 
- We’ll also learn how to define a class ourselves. 
 
Defining a class#
To create a new class, we use the class ClassName syntax.
## By convention, class names are capitalized
class Cat():
    
    # By default, make color "black"
    color = "black"
    
    # This is a custom *method* 
    def meow(self, n_times = 2):
        return "Meow" * n_times
    
    # This is another custom *method*
    def purr(self, n_times = 4):
        return "Purr" * n_times
Instantiating a class#
Now that we’ve defined a class, we can instantiate it.
- Instantiation means creating a particular instance of that class. - Analogy: “Cat” is an abstract concept/category, but “patroclus” could be a specific cat. 
 
- Syntax: - instance_name = ClassName()
## Create a cat object
patroclus = Cat()
# Use purr method
patroclus.purr()
'PurrPurrPurrPurr'
## Access attribute
patroclus.color
'black'
# Use meow method
patroclus.meow(n_times = 1)
'Meow'
Instance attributes#
The __init__ function allows us to define a class with custom attributes as well as methods.
- The - selfkeyword refers to specific instances of that class.
class Cat():    
    ## __init__ method allows custom color
    def __init__(self, color):
        self.color = color
        
    def meow(self, n_times = 2):
        return "Meow" * n_times
    def purr(self, n_times = 4):
        return "Purr" * n_times
## Create two cats with different colors
patroclus = Cat(color = "black")
bartimaues = Cat(color = "gray")
print("Patroclus is {x}".format(x = patroclus.color))
print("Bartimaues is {x}".format(x = bartimaues.color))
Patroclus is black
Bartimaues is gray
Check-in#
For an object person with the attribute height, how would you access that attribute?
- person.height
- person.height()
- height(person)
## Your response here
Solution#
You’d use person.height for the attribute.
Check-in#
For an object person with the method speak, how would you access that method?
- person.speak
- person.speak()
- speak(person)
## Your response here
Solution#
You’d use person.speak() for the method.
A more complex class.#
Let’s define a custom class called BankAccount. It should have the following features:
- It stores an attribute called - balance, which tells us how much money is in the account.
- It has a method called - deposit, which balance us to deposit a custom amount of money.- depositshould affect the value of- amount.
 
- It has a method called - withdraw, which allows us to take out a custom amount of money.- withdrawshould affect the value of- balance.
 
Try thinking through this yourself first, then we’ll discuss a solution.
### Your code here
Solution: BankAccount#
class BankAccount():
    
    def __init__(self, starting_amount):
        self.balance = starting_amount
    
    def deposit(self, cash):
        # Change amount by this much
        self.balance += cash
    
    def withdraw(self, cash):
        # Change balance
        self.balance -= cash
        # Return amount
        return cash
BankAccount in practice#
# Create an instance, with starting_amount = 10
my_account = BankAccount(starting_amount = 10)
my_account.balance
10
# Deposit 5 more dollars
my_account.deposit(5)
my_account.balance
15
# Withdraw 15 dollars
my_account.withdraw(15)
my_account.balance
0
Check-in#
Right now, withdraw doesn’t check to make sure we have enough money in the account. How could we change this method, so that it instead:
- Checks that - balance >= cash.
- If - balance >= cash, return- cashand change- balance.
- If - balance < cash,- printout a message saying: “Not enough in account!”
# Your code here
Finding out how a class works#
In CSS, you’ll probably use classes defined by other people more frequently than you define your own.
Thus, it’s important to know how to find out how a class works.
- How do I instantiate this class? 
- What kinds of methods does this class have? 
Using dir#
The dir keyword will list all attributes and methods associated with an object.
- The under-score in those attributes/methods (called dunders) are special features associated with most Python objects. 
dir(patroclus)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'color',
 'meow',
 'purr']
Other helpful resources#
- The - ?ClassNamesyntax will bring up a window giving you information about that class (i.e., the documentation).
- You can also search for this documentation on Google, e.g., “Python ClassName documentation”. 
- Finally, StackOverflow often has answers! 
Learning to navigate these resources is an important part of programming. For me, much of my time programming is spent learning about a custom object/class in Python and looking at examples of it in use.
Conclusion#
- This is by no means a complete introduction to classes. 
- An Intro to Programming class in CSE would spend considerably more time, as classes are a key part of object-oriented programming and software engineering. 
- For our purposes, it’s important to know what a class is, how to define a class, and how to find out information about classes. 
