An object bundles together information and related behavior.
Each list is an object. The information is the sequence of elements, and the behavior are
methods (like append
) plus slicing and bracket notation.
lyrics = ['Ring', 'ding', 'ding', 'ding', 'dingeringeding!']
lyrics[0] # 'Ring'
len(lyrics) # 5
lyrics[0] = 'Ring'
Similarly, each string is an object. The information is the sequence of characters, and the behavior
are methods (like split
) plus slicing and bracket notation.
what_fox_says = 'Hatee-hatee-hatee-ho'
what_fox_says[0:5] # Hatee
what_fox_says.split('-') # ['Hatee', 'hatee', 'hatee', 'ho']
Lists and strings have similar behavior, but not the same.
In fact, every data type you've used so far is an object.
Every object has a type, also known as its class
.
what_fox_says = 'Hatee-hatee-hatee-ho'
type(what_fox_says) # 'str'
lyrics = ['Ring', 'ding', 'ding', 'ding', 'dingeringeding!']
type(lyrics) # 'list'
int
: integers
float
: floating point numbers
bool
: Booleans
list
: lists
range
: ranges
str
: strings
dict
: dictionaries
Python includes a special syntax to create new classes.
The class definition:
class Fox:
species_name = 'Vulpes vulpes'
def __init__(self, name):
self.name = name
self.happiness = 0
def say(self):
return f'{self.name} says Wa-pa-pa-pa-pa-pow'
def play(self, num_hours):
self.happiness += num_hours
Making a new objects of that class:
pf = Fox('Pamela')
pf.say()
pf.play(2)
Let's break it down...
pf = Fox('Pamela')
The Fox()
expression is the constructor for the class.
When the constructor is called:
__init__
method of the class is called with the new object as its first argument (named self
), along with any additional arguments provided in the call expression
class Fox:
def __init__(self, name):
self.name = name
self.happiness = 0
Instance variables are data attributes that describe the state of an object.
This __init__
initializes 2 instance variables:
class Fox:
def __init__(self, name):
self.name = name
self.happiness = 0
The class methods can then change the values of those variables or assign new variables.
This expression...
pf.play(2)
...calls this function in the class definition:
class Fox:
def play(self, num_hours):
self.happiness += num_hours
pf.play
is a bound method:
a function which has its first parameter pre-bound to a particular value.
In this case, self
is pre-bound to pf
and num_hours
is set to 2.
It's equivalent to:
Fox.play(pf, 2)
All object attributes (which includes variables and methods) can be accessed with dot notation:
pf.play(2)
That evaluates to the value of the attribute looked up by play
in the object referenced by pf
.
The left-hand side of the dot notation can also be any expression that evaluates to an object reference:
foxes = [pf, hf]
foxes[0].play(2)
A class variable is an assignment inside the class that isn't inside a method body.
class Fox:
species_name = 'Vulpes vulpes'
Class variables are "shared" across all instances of a class because they are attributes of the class, not the instance.
pf = Fox('Pamela')
hf = Fox('Hunter')
pf.species_name # 'Vulpes vulpes'
hf.species_name # 'Vulpes vulpes'
Fox.species_name # 'Vulpes vulpes'
The class definition:
# Define a new type of data
class Fox:
# Set class variables
species_name = 'Vulpes vulpes'
# Set the initial values
def __init__(self, name):
self.name = name
self.happiness = 0
# Define methods
def say(self):
return f'{self.name} says Wa-pa-pa-pa-pa-pow'
def play(self, num_hours):
self.happiness += num_hours
Object instantiation and method invocation:
pf = Fox('Pamela')
pf.play(2)
There can be multiple instances of each class.
pina_bar = Product("Piña Chocolotta", 7.99,
["200 calories", "24 g sugar"])
cust1 = Customer("Coco Lover",
["123 Pining St", "Nibbsville", "OH"])
cust2 = Customer("Nomandy Noms",
["34 Shlurpalot St", "Buttertown", "IN"])
What are the classes here?
Product
, Customer
How many instances of each?
1 Product
, 2 Customer
class Customer:
salutation = "Dear"
def __init__(self, name, address):
self.name = name
self.address = address
def get_greeting(self):
return f"{self.salutation} {self.name},"
def get_formatted_address(self):
return "\n".join(self.address)
cust1 = Customer("Coco Lover",
["123 Pining St", "Nibbsville", "OH"])
What are the class variables? salutation
What are the instance variables? name
, address
A game where we take care of cute furry/ferocious animals:
Panda()
Lion()
Rabbit()
Vulture()
Elephant()
Food()
Let's start simple:
class Food:
def __init__(self, name, type, calories):
self.name = name
self.type = type
self.calories = calories
How would we use that class?
broccoli = Food("Broccoli Rabe", "veggies", 20)
bone_marrow = Food("Bone Marrow", "meat", 100)
class Elephant:
species_name = "African Savanna Elephant"
scientific_name = "Loxodonta africana"
calories_needed = 8000
def __init__(self, name, age=0):
self.name = name
self.age = age
self.calories_eaten = 0
self.happiness = 0
def play(self, num_hours):
self.happiness += (num_hours * 4)
print("WHEEE PLAY TIME!")
def eat(self, food):
self.calories_eaten += food.calories
print(f"Om nom nom yummy {food.name}")
if self.calories_eaten > self.calories_needed:
self.happiness -= 1
print("Ugh so full")
def interact_with(self, animal2):
self.happiness += 1
print(f"Yay happy fun time with {animal2.name}")
Object construction:
el1 = Elephant("Willaby", 5)
el2 = Elephant("Wallaby", 3)
el1.play(2)
el1.interact_with(el2)
class Rabbit:
species_name = "European rabbit"
scientific_name = "Oryctolagus cuniculus"
calories_needed = 200
def __init__(self, name, age=0):
self.name = name
self.age = age
self.calories_eaten = 0
self.happiness = 0
def play(self, num_hours):
self.happiness += (num_hours * 10)
print("WHEEE PLAY TIME!")
def eat(self, food):
self.calories_eaten += food.calories
print(f"Om nom nom yummy {food.name}")
if self.calories_eaten > self.calories_needed:
self.happiness -= 1
print("Ugh so full")
def interact_with(self, animal2):
self.happiness += 4
print(f"Yay happy fun time with {animal2.name}")
Object construction:
rabbit1 = Rabbit("Mister Wabbit", 3)
rabbit2 = Rabbit("Bugs Bunny", 2)
rabbit1.eat(broccoli)
rabbit2.interact_with(rabbit1)
Elephant | Rabbit |
---|---|
|
|
Elephant
and Rabbit
are both animals,
so they have similar attributes.
Instead of repeating code, we can inherit the code.
When multiple classes share similar attributes, you can reduce redundant code by defining a base class and then subclasses can inherit from the base class.
Tip: The base class is also known as the superclass.
The base class contains method headers common to the subclasses, and code that is used by multiple subclasses.
class Animal:
species_name = "Animal"
scientific_name = "Animalia"
play_multiplier = 2
interact_increment = 1
def __init__(self, name, age=0):
self.name = name
self.age = age
self.calories_eaten = 0
self.happiness = 0
def play(self, num_hours):
self.happiness += (num_hours * self.play_multiplier)
print("WHEEE PLAY TIME!")
def eat(self, food):
self.calories_eaten += food.calories
print(f"Om nom nom yummy {food.name}")
if self.calories_eaten > self.calories_needed:
self.happiness -= 1
print("Ugh so full")
def interact_with(self, animal2):
self.happiness += self.interact_increment
print(f"Yay happy fun time with {animal2.name}")
To declare a subclass, put parentheses after the class name and specify the base class in the parentheses:
class Panda(Animal):
Then the subclasses only need the code that's unique to them. They can redefine any aspect: class variables, method definitions, or constructor. A redefinition is called overriding.
The simplest subclass overrides nothing:
class AmorphousBlob(Animal):
pass
Subclasses can override existing class variables and assign new class variables:
class Rabbit(Animal):
species_name = "European rabbit"
scientific_name = "Oryctolagus cuniculus"
calories_needed = 200
play_multiplier = 8
interact_increment = 4
num_in_litter = 12
class Elephant(Animal):
species_name = "African Savanna Elephant"
scientific_name = "Loxodonta africana"
calories_needed = 8000
play_multiplier = 4
interact_increment = 2
num_tusks = 2
If a subclass overrides a method, Python will use that definition instead of the superclass definition.
class Panda(Animal):
species_name = "Giant Panda"
scientific_name = "Ailuropoda melanoleuca"
calories_needed = 6000
def interact_with(self, other):
print(f"I'm a Panda, I'm solitary, go away {other.name}!")
How would we call that method?
panda1 = Panda("Pandeybear", 6)
panda2 = Panda("Spot", 3)
panda1.interact_with(panda2)