Objects and Classes
#
OverviewThis lesson walks through creating classes in Python. The lesson starts with We Dos for creating a class and instantiating objects from that class. It's followed by a We Do for class and instance variables. It ends with a few partner exercises, then a series of Knowledge Checks.
#
Learning ObjectivesAfter this lesson, you will be able toβ¦
- Define a class.
- Instantiate an object from a class.
- Create classes with default instance variables.
#
Duration50 MINUTES
#
AgendaDuration | Activity |
---|---|
3 mins | Welcome |
7 mins | Class Overview |
15 mins | Creating Classes |
5 mins | Class Variables |
17 mins | Exercises |
3 mins | Summary |
#
BlueprintsAll cars have things that make them a Car
. Although the details might be different, every type of car has the same basics β it's off the same blueprint, with the same properties and actions.
Property: A shape (could be hatchback or sedan).
Property: A color (could be red, black, blue, or silver).
Property: Seats (could be between 2 and 5).
Action: Can drive.
Action: Can park.
When we make a car, we can vary the values of these properties. Some cars have economy engines, some have performance engines. Some have four doors, others have two. However, they are all types of
Car
s.Take particular note of the small "c" versus the big "C"!
Can you think of other commonalities of cars β get them thinking about an archetypal car.
#
Introduction: Objects and ClassesThese properties and behaviors can be thought of as variables and functions.
Car
blueprint:
- Properties (variables):
shape
,color
,seats
- Actions (functions):
drive()
andpark()
An actual car might have:
# **Properties - Variables**:- shape = "hatchback"- color = "red", "black", "blue", or "silver"- seats = 2
# **Actions - Functions:**- drive()- park()- reverse()
Discussion: What might a blueprint for a chair look like?
Talking Points:
- Every day, we interact with objects like chairs, beverages, cars, other people, etc. These objects have properties that define them and behaviors we can execute to interact with them.
#
Discussion: Python ClassesIn Python, the concept of blueprints and objects is common. A class is the blueprint for an object. Everything you declare in Python is an object, and it has a class.
Consider the List
class β every list you make has the same basic concept.
Variables:
- Elements: What's in the list! E.g.,
my_list = [element1, element2, element3]
.
Functions that all lists have:
my_list.pop()
,my_list.append()
,my.list.insert(index)
What behaviors and properties do you think are in the Dictionary
class? The Set
class?
Talking Points:
- Similarly, you will hear people say that "everything is an object" in Python. Python is an object-oriented programming language.
- What this means is that nearly every variable you declare actually has a set of properties and functions that it can use β it is an object.
- Every string, number, list, dictionary, etc. has a set of behaviors and properties that are "baked in" because they are instances of a class.
- Every list you declare has properties (the values in it) and behaviors β functions like
append()
andpop()
. - In Python, there is a built-in
List
class, which has the ability to hold values, and built-in list functions likeappend()
andpop()
. When you declare a list in Python, you're making your own list object that's a variation of theList
class.
Dog
Class#
Discussion: A We can make a class for anything! Let's create a Dog
class.
The objects might be greyhound
, goldenRetriever
, corgi
, etc.
Think about the Dog
blueprint. What variables might our class have? What functions?
Pro tip: When functions are in a class, they are called "methods." They're the same thing!
Pro tip: While objects are named in snake_case, classes are conventionally named in TitleCase.
#
We Do: Defining ClassesFollow along! Let's create a new file, Dog.py
.
Class definitions are similar to function definitions, but instead of def
, we use class
.
Let's declare a class for Dog
:
class Dog(): # We'll define the class here. # Our dog will have two variables: name and age.
Pro tip: Files are usually named for their class, so the Dog
class is in Dog.py
.
Talking Points:
- It's very common in programming to make our own classes to organize data in the ways we want. Python gives us, for example, a string and an integer.
- What if we want to store a bunch of data where each item contains a string and an integer and a function that prints them out nicely?
- We can make a class for that, and then each object we make from that class will have that all baked in.
__init__
Method#
We Do: The What first? Every class starts with an __init__
method. It's:
- Where we define the class' variables.
- Short for "initialize."
- "Every time you make an object from this class, do what's in here."
Let's add this:
class Dog: def __init__(self, name="", age=0): # Note the optional parameters and defaults. self.name = name # All dogs have a name. self.age = age # All dogs have an age.
Note: self
means "each individual object made from this class." Not every "dog" has the same name!
Self
is tough! It will make more sense after you start creating objects. Don't spend more than a few minutes on it β go back to it when comparing instance versus class variables.Call out the default values, or optional parameters, as we very recently learned them.
Method means function!
When we make an object, we'll first set its variables.
The first argument passed to the
__init__
function,self
, is required when defining methods for classes. Theself
argument is a reference to a future instantiation of the class. In other words,self
refers to each individual dog.This lets each object made from a class keep references to its own data and function members. Not every "dog" has the same attributes, so we want individual cars to maintain their own attributes.
Python allows us to provide default values for parameters in any function we provide. Here, if no
name
orage
values are provided when aDog
is initialized, they will default. To create default values, we assign values to the parametercapacity
inside the parentheses. You've seen this!
bark_hello()
Method#
We Do: Adding a All dogs have the behavior bark
, so let's add that. This is a regular function (method), just inside the class!
class Dog: def __init__(self, name="", age=0): # Note the defaults.
self.name = name # All dogs have a name. self.age = age # All dogs have an age.
# All dogs have a bark function. def bark_hello(self): print("Woof! I am called", self.name, "; I am", self.age, "human-years old.")
We're done defining the class!
- Note that it takes
self
! This will be tough to remember. Point out that it matches how the variable was declared.
#
Aside: Instantiating Objects From ClassesNow we have a Dog
template!
Each dog
object we make from this template:
Has a name.
Has an age.
Can bark.
Take special note of the lowercase "d!"
Dog
Object?#
We Do: How Do We Make a We call our class name like we call a function β passing in arguments, which go to the init
.
Add this under your class (non-indented!):
# Declare the objects.gracie = Dog("Gracie", 8)spitz = Dog("Spitz", 5)buck = Dog("Buck", 3)
# Test them out!gracie.bark_hello()print("This dog's name is", gracie.name)print("This dog's age is", gracie.age)spitz.bark_hello()buck.bark_hello()
Try it! Run Dog.py
like a normal Python file: python Dog.py
.
- Map out that these variables go to
__init__
to get created. All arguments go to__init__
! - You have a working class! Go back through the whole code and make sure you understand.
Talking Points:
- This will create a new object according to our
Dog
class specification. - Python runs our
__init__
method to initialize the object. - Here, we are telling our
__init__
method to set the name of thisdog
to'Gracie'
and set her age to8
years old. - Even though
self
is listed as a parameter for thebark_hello()
function, we don't pass it into the function. It happens automatically.
#
We Do: Adding Print__init__
is just a method. It creates variables, but we can also add a print
statement! This will run when we create the object.
class Dog: def __init__(self, name="", age=0): self.name = name self.age = age print(name, "created.") # Run when init is finished.
def bark_hello(self): print("Woof! I am called", self.name, "; I am", self.age, "human-years old.")
fox = Dog("Fox") # Note that "Fox created." prints β and we're using the default age.fox.bark_hello()
Try it!
- Run this a few times to show the default variables. Take out the default for name to observe that variables don't need a default value.
Talking Points:
- Reminder: "Method" is a function in a class.
- Note that
print
statements can be anywhere β it's not a variable!__init__
is a method. - The
__init__
method will execute once and only once when you create a new object from a class. Note that theprint
statement never happens again.
#
Quick Review: ClassesA class is a blueprint for an object. Some classes are built into Python, like List
. We can always make a list
object.
We can make a class for anything!
# Created like a function; TitleCaseclass Dog:
# __init__: A method (function) that happens just once, when the object is created. def __init__(self, name="", age=0): # What's passed in to the class is used here. # Set variables for each. self.name = name self.age = age print(name, "created.") # This will run when the __init__ method is called.
# Classes can have as many methods (functions) as you'd like. def bark_hello(self): print("Woof! I am called", self.name, "; I am", self.age, "human-years old.")
fox = Dog("Fox") # Creating the object calls __init__. Objects are snake_case.print("This dog's name is", fox.name) # The object now has those variables!fox.bark_hello() # The object now has those methods and variables!
Teaching Tips:
- Add your own reasons for why classes are useful.
- Do a quick check for understanding.
- Run down the comments in the code like they're bullet points!
#
Discussion: What About Tea?Let's make a TeaCup
class.
What variables would a cup of tea have?
What methods?
Discuss suggestions for properties for a
Tea
class.The exercise has
capacity
,amount
,fill
,empty
, anddrink
.
TeaCup
Class#
A Potential We could say:
Variables:
- A total
capacity
. - A current
amount
.
Methods:
fill()
our cup.empty()
our cup.drink()
some tea from our cup.Given a well-defined cup of tea, we can use the class definition to create instances of the class.
Each instance of the
TeaCup
class can have a differentcapacity
and keep track of differentamounts
.Although different, properties are affected by actions like
fill()
,empty()
, anddrink()
similarly.
TeaCup
Class#
Example: A Here's what a TeaCup
class definition might look like in Python:
class TeaCup: def __init__(self, capacity): # Python executes when a new cup of tea is created. self.capacity = capacity # Total ounces the cup holds. self.amount = 0 # Current ounces in the cup. All cups start empty!
def fill(self): self.amount = self.capacity
def empty(self): self.amount = 0
def drink(self, amount_drank): self.amount -= amount_drank # If it's empty, it stays empty! if self.amount == 0: self.amount = 0
steves_cup = TeaCup(12) # Maybe a fancy tea latte.yis_cup = TeaCup(16) # It's a rough morning!brandis_cup = TeaCup(2) # Just a quick sip.
- This class doesn't take in
amount
! It's set as a variable, but not passed in. Can you explain this? - Note that the object declarations have to go below the class. Show the error that occurs if you try calling
steves_cup
first. - Call each function β
fill()
,drink()
with a different number for each, and printing the amount left withcup.amount
.
#
Quick Knowledge Checkclass TeaCup(): def __init__(self, capacity = 8): self.capacity = capacity self.amount = 0
When will the capacity be 8
?
- Answer: When no capacity is passed in when it's declared.
#
Variables for All Class ObjectsNext up: new types of class variables!
Let's revisit our Dog
class:
class Dog(): def __init__(self, name="", age=0): self.name = name self.age = age print(name, "created.")
def bark_hello(self): print("Woof! I am called", self.name, "; I am", self.age, "human-years old")
What if there are variables that we want across all dogs?
For example, can we count how many dog
objects we make and track it in the class?
- Our
Dog
class had variables attached toself
that exist independently for each object that's created.- Each object instance has its own copies of these variables, and they can vary across objects.
- We can attach variables to the class itself so that there's one single thing that exists for an entire class.
#
I Do: Class vs. Instance MembersWe already have instance variables, which are specific to each dog
object (each has its own name!).
A class variable is specific to the class, regardless of the object. It's created above __init__
.
class Dog(): ### Here, we define class variables. ### # These are the same for ALL dogs. total_dogs = 0
def __init__(self, name="", age=0):
### These are instance variables. ### self.name = name self.age = age print(name, "created.")
def bark_hello(self): print("Woof! I am called", self.name, "; I am", self.age, "human-years old") print("There are", Dog.total_dogs, "dogs in this room!") # There's no "self" β we call the Dog class name!
molly = Dog("Molly", 8)molly.bark_hello()
sheera = Dog("Sheera", 5)sheera.bark_hello()
Talking Points:
- Our
Dog
class had variables attached toself
that exist independently for each object that's created.- These are called instance variables.
- Each object instance has its own copies of these variables, and they can vary across objects.
- We can attach variables to the class itself so that there's one single thing that exists for an entire class.
- These are called class variables.
#
I Do: Tallying DogsWe can increment the class
variable any time.
class Dog(): total_dogs = 0 def __init__(self, name="", age=0): self.name = name self.age = age Dog.total_dogs += 1 # We can increment this here! print(name, "created:")
def bark_hello(self): print("Woof! I am called", self.name, "; I am", self.age, "human-years old.") print("There are", Dog.total_dogs, "dogs in this room!")
molly = Dog("Molly", 8)molly.bark_hello()
sheera = Dog("Sheera", 5)sheera.bark_hello()
Talking Points:
- We can keep a tally of how many
dog
s we have running around in our app. - We could put a copy of the tally in each
dog
object, but that's not efficient, as we would be duplicating a value in memory multiple times, and we would have to update the value in everydog
object in order to keep it accurate. - It's much better if we can store it in the class. That way, each
dog
object can access it, but we only need to store it and set it in one place. - Finally, we create a new
dog
. The__init__
method increments thetotal_dogs
counter, which is stored in theDog
class itself. We can access the value stored inDog.total_dogs
inside our script, and eachdog
object can access it from their own functions.
#
Partner Exercise: Create a Music Genre ClassPair up! Create a new file, Band.py
.
- Define a class,
Band
, with these instance variables:"genre"
,"band_name"
, and"albums_released"
(defaulting to0
). - Give
Band
a method calledprint_stats()
, which prints a string like"The rock band Queen has 15 albums."
- Create a class variable,
number_of_bands
, that tracks the number of bands created.
Test your code with calls like:
my_band = Band("Queen", 15, "rock")
Bonus: If the genre provided isn't "pop"
, "classical"
, or "rock"
, print out "This isn't a genre I know."
5-10 MINUTES
Talking Points:
- Imagine that you are working with music data of all different types of genres and want to ultimately define three different classes of music (pop, classical, and rock).
- Things to think about:
- Starting values for variables should be set in the
__init__
method. - Class variables are declared inside the class but outside any methods.
- Instance variables are declared inside the
__init__
method. - Does your
__init__
method need to accept any parameters?
- Starting values for variables should be set in the
BankAccount
Class#
Partner Exercise: Create a Switch drivers! Create a new class (and file), Bank.py
.
Bank accounts should:
- Be created with the
accountType
property (either"savings"
or"checking"
). - Keep track of its current
balance
, which always starts at0
. - Have access to
deposit()
andwithdraw()
methods, which take in an integer and updatebalance
accordingly. - Have a class-level variable tracking the total amount of money in all accounts, adding or subtracting whenever
balance
changes.
Bonus: Start each account with an additional overdraftFees
property that begins at 0
. If a call to withdraw()
ends with the balance
below 0
, then overdraftFees
should be incremented by 20
.
10 MINUTES
Talking Points:
- (The same as above.)
- Things to think about:
- Starting values for variables should be set in the
__init__
method. - Class variables are declared inside the class but outside any methods.
- Instance variables are declared inside the
__init__
method. - Does your
__init__
method need to accept any parameters?
- Starting values for variables should be set in the
#
Knowledge Check: Select the Best AnswerConsider the following class definition for Cat()
:
class Cat(Animal): def __init__(self, name='Lucky'): self.name = name self.fur = short
How would you instantiate a Cat
object with the name
attribute 'Furball'
?
mycat = Cat(name='Furball')
furball = Cat()
mycat = Cat(self, name='Furball')
mycat = Cat.init(name='Furball')
Answer:
- The
__init__
function is automatically called when creating an object with theCat(name='Furball')
syntax.
#
Knowledge Check: Select All That ApplyWhich of the following statements are true about the self
argument in class definitions?
- The user does not need to supply
self
when using instance methods. - The
self
argument is a reference to the instance object. - Any variable assigned with
self
(e.g.,self.var
) will be shared across instances of the class. - With an instance object,
obj
, enteringobj.self.var
will provide the value forvar
for that instance.
Answers:
- The user does not need to supply
self
when using instance methods. - The
self
argument is a reference to the instance object.
Correct response explanation:
self
is automatically passed into an instance method when you call it.self
refers to the instance and NOT the class.self.var
will not be shared between instances. Instances have no explicitself
attribute.
#
Knowledge Check: Select the Best Answer IIConsider the following code:
class Shape(object): possible = ["triangle", "square", "circle", "pentagon", "polygon", "rectangle"]
def __init__(self, label="triangle"): self.label = label
def is_possible(self): if self.label in self.possible: print("This is possible") else: print("This is impossible")
square = Shape(label="square")wormhole = Shape(label="wormhole")square.possible.append("wormhole")
If you were to enter wormhole.is_possible()
, would the outcome be "This is possible"
or "This is impossible"
?
Answer:
This is possible
Correct answer explanation:
- The possible list is defined at the class level as opposed to as an instance variable. When we append the string
'wormhole'
to the possible list of thesquare
object, this list is shared with the wormhole instance. Therefore the output will beThis is possible
.
#
Summary: DiscussionLet's chat! Can anyone explain:
- What a class is?
- What
__init__
does? - What an object is?
- The point of
self
? - The two types of variables?
#
Summary and Q&AClass:
- A pre-defined structure that contains attributes and behaviors grouped together.
- The blueprint.
- Defined via a method call.
- Contains an
__init__
method that takes in parameters to be assigned to an object. - E.g., the
Dog
class; theList
class.
Object:
- An instance of a class structure.
- The items built from the blueprint.
- E.g., the
gracie
object; themy_list
object.
#
Summary: Types of Variables in a ClassInstance variables:
- Contain data types declared in the class but defined in each object.
- Each
dog
has its own name and age. - Each
my_list
has its own elements.
Class variables:
- Contain data and actions that span across all objects.
- How many
dog
objects are there in total? - The
self
keyword lets us distinguish between variables that exist at the class level versus in each object.