Object-Oriented Programming and Class Design

 
M
o
d
u
l
e
 
5
 
O
b
j
e
c
t
-
O
r
i
e
n
t
e
d
 
P
r
o
g
r
a
m
m
i
n
g
a
n
d
 
c
l
a
s
s
 
D
e
s
i
g
n
 
M
o
t
i
v
a
t
i
o
n
 
Object-Oriented Programming (OOP) is based on the
concept of 
classes
, from which 
objects
 are created.
 
In essence, classes work as a blueprint for creating
something, while objects created from that class are
the actual thing.
 
 
C
l
a
s
s
e
s
 
Using classes, we’re actually creating new data types!
A class represents the 
concept
 of things in the real world, like
Dogs.
Classes follow a template, and have:
 a name
 variables (often called “attributes” or “fields”)
 functions (which are now called “methods”, “behaviors” or
“member functions”)
 
T
h
e
 
S
m
a
l
l
e
s
t
 
C
l
a
s
s
 
 
c
lass Dog:
    pass
 
O
h
 
n
o
!
 
W
h
a
t
 
h
a
v
e
 
w
e
 
d
o
n
e
?
 
We’ve:
 created a 
new (complex) data type
!
 created the “concept” of a Dog
 
We don’t have any Dogs yet, 
just the concept
 
O
b
j
e
c
t
s
 
An 
object:
 is an entity in the real world that can be
distinctly identified
 might represent a 
particular
 dog, employee,
student, etc.
 has a unique 
identity
, 
state
, and 
behavior
.
 
 
Object Identity, State and Behavior
 
An object has a unique 
identity
 as it represents one entity.
 
The object 
state
 consists of a set of 
data fields
 (instance
variables or properties) with their 
current values
.
 
The object 
behavior
 is defined by a set of 
methods
 
 
Example:
 Class 
Student
 that describes individual students,
such that each student has a unique ID, has his/her own
state (information), and all students share same behavior
(methods).
 
Example: Class Bank Account
 
 
A
 
r
e
a
l
 
l
i
f
e
 
e
x
a
m
p
l
e
 
Let’s make a Dog!
Attributes (characteristics)
rabid or not rabid (boolean)
weight (a number)
name (string)
Behaviors
growl
eat
 
S
t
e
p
 
1
:
 
T
h
e
 
S
k
e
l
e
t
o
n
 
class Dog:
    pass
 
S
t
e
p
 
2
:
 
A
d
d
 
a
t
t
r
i
b
u
t
e
s
 
class Dog:
  
# States of a Dog
    rabid = False
    weight = 0.0
    name = 
“”
 
class Dog:
 
# States of a Dog
  
rabid = False
  
weight = 0.0
  
name = “”
 
  
# Behaviors of a Dog
  
def eat(self, food):
   
weight += food
   
print(self.name + 
“ now weighs “ 
+ str(weight))
 
  
def growl(self):
   
print(self.name + 
“ says grr”
)
 
S
t
e
p
 
3
:
 
A
d
d
i
n
g
 
b
e
h
a
v
i
o
r
s
 
You may have noticed that the methods
inside the class always have at least one
parameter, the “
self
” parameter.
This parameter is necessary for accessing
the fields inside the object
You will not pass any arguments when a
class method only has the 
self
 parameter.
 
S
e
l
f
 
k
e
y
w
o
r
d
 
# empty code file
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1 = Dog()
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1 = Dog()
d1.name = 
“Alice”
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = False
 
weight = 0.0
 
name = “Alice”
 
d1 = Dog()
d1.name = 
“Alice”
d1.rabid = True
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = True
 
weight = 0.0
 
name = “Alice”
 
d1 = Dog()
d1.name = 
“Alice”
d1.rabid = True
d1.weight = 50.0
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = True
 
weight = 50.0
 
name = “Alice”
 
d1 = Dog()
d1.name = 
“Alice”
d1.rabid = True
d1.weight = 50.0
 
d2 = Dog()
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = True
 
weight = 50.0
 
name = “Alice”
 
d2
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1 = Dog()
d1.name = 
“Alice”
d1.rabid = True
d1.weight = 50.0
 
d2 = Dog()
d2.name = 
“Bob”
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = True
 
weight = 50.0
 
name = “Alice”
 
d2
 
rabid = False
 
weight = 0.0
 
name = “Bob”
 
d1 = Dog()
d1.name = 
“Alice”
d1.rabid = True
d1.weight = 50.0
 
d2 = Dog()
d2.name = 
“Bob”
d2.weight = 30.0
 
C
r
e
a
t
i
n
g
 
D
o
g
s
Memory
 
d1
 
rabid = True
 
weight = 50.0
 
name = “Alice”
 
d2
 
rabid = False
 
weight = 30.0
 
name = “Bob”
 
W
e
v
e
 
c
r
e
a
t
e
d
 
2
 
d
o
g
s
!
 
Notice that they start with the same fields, and the
same values in those fields.
However, we edited the individual objects to hold
data that was particular to that object
Thus, accessing the fields from each object will give
us different data:
 
print(d1.name) 
# prints “Alice”
 
print(d2.name) 
# prints “Bob”
 
T
h
e
 
.
 
o
p
e
r
a
t
o
r
 
“Dot” operator used to
Get to an instance’s attributes
Get to an instance’s methods
Basically, get inside the instance
Format:
<instance>.<attribute or method>
 
U
s
i
n
g
 
t
h
e
 
.
 
o
p
e
r
a
t
o
r
 
d1 = Dog()
d1.name = 
“Alice”
d1.rabid = True
d1.weight = 50.0
d2 = Dog()
d2.name = 
“Bob”
d2.weight = 30.0
d1.eat(2)  
    
# Alice weighs 52 lbs
d2.growl()
    
# Bob says GRRRR
d1.eat(4)
    
# Alice weighs 56 lbs
d2.eat(-1)
    
#
 Bob weighs 29 lbs
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
This is a special method
Used to give initial values to ALL attributes
Is activated when someone creates an instance of the
class (i.e.: creates an object)
In most languages, the name of this method MUST
be the same name as the class
In Python, the name of this method must be
__init__
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
Dog without a constructor:
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
 
Dog with a constructor:
class Dog:
 
def __init__(self):
  
self.rabid = False
  
self.weight = 0.0
  
self.name = 
“”
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
Seems like extra work. Why initialize the fields inside the
constructor instead of directly in the class body?
Allows initializing the class fields in the constructor parameters
Prevents unintended behavior when using mutable fields
 
class Dog:
 
def __init__(self, weight, rabid = False, name = 
“”
):
  
self.rabid = rabid
  
self.weight = weight
  
self.name = 
name
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
I
n
i
t
i
a
l
i
z
i
n
g
 
f
i
e
l
d
s
 
 
class Dog:
 
def __init__(self, weight, rabid = False, name = 
“”
):
 
  
self.rabid = rabid
  
self.weight = weight
  
self.name = 
name
# Dogs now need at least 1 argument before they can be
# created: the weight
d1 = Dog(45, name = 
“Charlie”
)
 
rabid = False
 
weight = 45
 
name = “Charlie”
 
d1
 
D
e
s
i
g
n
i
n
g
 
t
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
Constructors will vary, depending on design
Ask questions:
Are all Dogs born with the same rabid state? (yes – they
are all born non-rabid)
Are all Dogs born with the same weight?  (
no
 – they are
born with different weights)
Are all Dogs born with the same name? (
no
 – they all
have different names)
If ever “no”, then you need information passed in as
parameters.
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
C
l
a
s
s
 
v
s
 
I
n
s
t
a
n
c
e
 
f
i
e
l
d
s
 
Before we start talking about mutable fields, let’s
talk about the difference between 
class
 and
instance
 fields
Without the constructor, the Dog class looked like
this:
 
class Dog:
  
rabid = False
  
weight = 0.0
  
name = 
“”
 
 
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
C
l
a
s
s
 
v
s
 
I
n
s
t
a
n
c
e
 
f
i
e
l
d
s
 
Even before we create our first Dog object, we
already have one: The class itself.
This allows us to change the default values of newly
created objects
d1 = Dog() 
# False, 0.0, “”
Dog.rabid = True 
# Changed rabid for future Dogs
Dog.weight = 200 
# Changed weight for future Dogs
d2 = Dog() 
# True, 200, “”
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
C
l
a
s
s
 
v
s
 
I
n
s
t
a
n
c
e
 
f
i
e
l
d
s
 
When accessing a field using the class name, we say
that field belongs to the class
When accessing a field of a specific object, we say
that field belongs to that instance (or object)
In practice, what’s actually happening is that 
a class
field is shared across all newly created objects until
an assignment is done
After the first assignment operation, the object will
have its own copy of the field
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
Memory
 
Dog
 
rabid = False
 
weight = 0.0
 
name = “”
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
Memory
 
Dog
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1
 
d1 has no
fields. Its
fields come
from Dog
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
# d1 now has its own
# copy of rabid
d1.rabid = True
Memory
 
Dog
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1
 
rabid = 
True
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
d1.rabid = True
print(d1.weight)
 
# prints 0.0
print(d1.rabid) 
 
# prints True
Memory
 
Dog
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1
 
rabid = 
True
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
d1.rabid = True
print(d1.weight)
print(d1.rabid)
d2 = Dog()
Memory
 
Dog
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1
 
rabid = True
 
d2
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
d1.rabid = True
print(d1.weight)
print(d1.rabid)
d2 = Dog()
print(d2.rabid) 
# prints False
Memory
 
Dog
 
rabid = False
 
weight = 0.0
 
name = “”
 
d1
 
rabid = True
 
d2
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
d1.rabid = True
print(d1.weight)
print(d1.rabid)
d2 = Dog()
print(d2.rabid) 
# prints False
Dog.rabid = None
Memory
 
Dog
 
rabid = 
None
 
weight = 0.0
 
name = “”
 
d1
 
rabid = True
 
d2
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
W
h
a
t
 
i
s
 
a
c
t
u
a
l
l
y
 
h
a
p
p
e
n
i
n
g
 
class Dog:
 
rabid = False
 
weight = 0.0
 
name = 
“”
d1 = Dog()
d1.rabid = True
print(d1.weight)
print(d1.rabid)
d2 = Dog()
print(d2.rabid) 
# prints False
Dog.rabid = None
print(d2.rabid) 
# prints None
print(d1.rabid) 
# still prints True
Memory
 
Dog
 
rabid = None
 
weight = 0.0
 
name = “”
 
d1
 
rabid = True
 
d2
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
C
l
a
s
s
 
v
s
 
I
n
s
t
a
n
c
e
 
f
i
e
l
d
s
 
To reiterate: when an object doesn’t have a field, it
will reach up to the Class fields.
You can force an object to have its own fields by:
Doing an assignment operation on the object’s field
d1.name = 
“Alice”
Initializing the field in the constructor
def __init__(self):
self.name = 
“Alice”
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
Normally, it makes no difference if an object has its
own copy of the field or if it is using the classes’
field
This is because the object will have its own copy
once an assignment operation is done
But this is a big problem for mutable fields (like lists)
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
class Student:
 
name = 
“”
class Classroom:
 
list_of_students = [] 
# the danger
 
s1 = Student()
s1.name = 
“Alice”
s2 = Student()
s2.name = 
“Bob”
# all normal so far
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
class Student:
 
name = 
“”
class Classroom:
 
list_of_students = [] 
# the danger
 
s1 = Student()
s1.name = 
“Alice”
s2 = Student()
s2.name = 
“Bob”
 
c1 = Classroom() 
# created a classroom
c2 = Classroom() 
# created another classroom
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
class Student:
 
name = 
“”
class Classroom:
 
list_of_students = [] 
# the danger
 
s1 = Student()
s1.name = 
“Alice”
s2 = Student()
s2.name = 
“Bob”
 
c1 = Classroom() 
# created a classroom
c2 = Classroom() 
# created another classroom
 
c1.list_of_students.append(s1) 
# added Alice to class 1
c2.list_of_students.append(s2) 
# added Bob to class 2
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
class Student:
 
name = 
“”
class Classroom:
 
list_of_students = [] 
# the danger
 
s1 = Student()
s1.name = 
“Alice”
s2 = Student()
s2.name = 
“Bob”
 
c1 = Classroom() 
# created a classroom
c2 = Classroom() 
# created another classroom
 
c1.list_of_students.append(s1) 
# added Alice to class 1
c2.list_of_students.append(s2) 
# added Bob to class 2
 
print(c1) 
# prints [‘Alice’, ‘Bob’] 
THIS IS A PROBLEM
print(c2) 
# prints [‘Alice’, ‘Bob’] 
BOTH CLASSROOMS ARE SHARING THE SAME STUDENTS
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
What happened?
Adding Alice to Classroom 1 added her to Classroom 2
and adding Bob to Classroom2 added him to Classroom
1
Why?
Because the list_of_students field belongs to the class.
Given that c1 and c2 don’t have their individual copies,
they are sharing the one from the class
We never assigned a list_of_students field to c1 or c2,
we appended information to it
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
(
s
o
l
v
i
n
g
 
t
h
e
 
p
r
o
b
l
e
m
)
 
class Student:
 
name = 
“”
class Classroom:
 
list_of_students = [] 
# the danger
 
s1 = Student()
s1.name = 
“Alice”
s2 = Student()
s2.name = 
“Bob”
 
c1 = Classroom() 
# created a classroom
c1.list_of_students = [] 
# c1 now has its own copy of list_of_students
c2 = Classroom() 
# created another classroom
c2.list_of_students = [] 
# c2 now has its own copy of list_of_students
 
c1.list_of_students.append(s1) 
# added Alice to class 1
c2.list_of_students.append(s2) 
# added Bob to class 2
 
print(c1) 
# prints [‘Alice’] 
Problem solved
print(c2) 
# prints [ ‘Bob’] 
Problem solved
 
T
h
e
 
C
o
n
s
t
r
u
c
t
o
r
 
 
M
u
t
a
b
l
e
 
f
i
e
l
d
s
 
(
s
o
l
v
i
n
g
 
t
h
e
 
p
r
o
b
l
e
m
)
 
class Student:
 
name = 
“”
class Classroom:
 
def __init__(self):
  
self.list_of_students = [] 
# list created inside the constructor is now individual to every object
 
s1 = Student()
s1.name = 
“Alice”
s2 = Student()
s2.name = 
“Bob”
 
c1 = Classroom() 
# created a classroom
c2 = Classroom() 
# created another classroom
 
c1.list_of_students.append(s1) 
# added Alice to class 1
c2.list_of_students.append(s2) 
# added Bob to class 2
 
print(c1) 
# prints [‘Alice’] 
Problem solved
print(c2) 
# prints [ ‘Bob’] 
Problem solved
 
Summary
 
A class:
 has attributes (which are just variables)
 has a constructor which is used to initialize attributes
 has other methods (like eat and growl)
 is a blueprint (template) for creating objects
 creates a new data type
 
An object:
 is an instance of a class
 has a state (variables) that is independent from others
trying to access a variable that the object doesn’t have prompts
the object to reach to the class for that variable
mutable fields at the class level need to be handled with care
 
 
 
 
Slide Note
Embed
Share

Object-Oriented Programming (OOP) is centered around classes that serve as blueprints for creating objects. Classes define the structure and behavior of objects, providing a framework for modeling real-world entities. By creating classes and objects, developers can efficiently represent and manipulate complex data types and systems.

  • OOP
  • Class Design
  • Objects
  • Programming Paradigm
  • Data Modeling

Uploaded on Sep 26, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. Module 5 Module 5 Object Object- -Oriented Programming Oriented Programming and class Design and class Design

  2. Motivation Motivation Object-Oriented Programming (OOP) is based on the concept of classes, from which objects are created. In essence, classes work as a blueprint for creating something, while objects created from that class are the actual thing.

  3. Classes Classes Using classes, we re actually creating new data types! A class represents the concept of things in the real world, like Dogs. Classes follow a template, and have: a name variables (often called attributes or fields ) functions (which are now called methods , behaviors or member functions )

  4. The Smallest Class The Smallest Class class Dog: pass

  5. Oh no! What have we done? Oh no! What have we done? We ve: created a new (complex) data type! created the concept of a Dog We don t have any Dogs yet, just the concept

  6. Objects Objects An object: is an entity in the real world that can be distinctly identified might represent a particular dog, employee, student, etc. has a unique identity, state, and behavior.

  7. Object Identity, State and Behavior An object has a unique identity as it represents one entity. The object state consists of a set of data fields (instance variables or properties) with their current values. The object behavior is defined by a set of methods Example: Class Student that describes individual students, such that each student has a unique ID, has his/her own state (information), and all students share same behavior (methods).

  8. Example: Class Bank Account

  9. A real life example A real life example Let s make a Dog! Attributes (characteristics) rabid or not rabid (boolean) weight (a number) name (string) Behaviors growl eat

  10. Step 1: The Skeleton Step 1: The Skeleton class Dog: pass

  11. Step 2: Add attributes Step 2: Add attributes class Dog: # States of a Dog rabid = False weight = 0.0 name =

  12. Step 3: Step 3: Adding behaviors class Dog: # States of a Dog rabid = False weight = 0.0 name = # Behaviors of a Dog def eat(self, food): weight += food print(self.name + now weighs + str(weight)) def growl(self): print(self.name + says grr )

  13. Self keyword Self keyword You may have noticed that the methods inside the class always have at least one parameter, the self parameter. This parameter is necessary for accessing the fields inside the object You will not pass any arguments when a class method only has the self parameter.

  14. Creating Dogs Creating Dogs # empty code file Memory

  15. Creating Dogs Creating Dogs d1 = Dog() Memory d1 rabid = False weight = 0.0 name =

  16. Creating Dogs Creating Dogs d1 = Dog() d1.name = Alice Memory d1 rabid = False weight = 0.0 name = Alice

  17. Creating Dogs Creating Dogs d1 = Dog() d1.name = Alice d1.rabid = True Memory d1 rabid = True weight = 0.0 name = Alice

  18. Creating Dogs Creating Dogs d1 = Dog() d1.name = Alice d1.rabid = True d1.weight = 50.0 Memory d1 rabid = True weight = 50.0 name = Alice

  19. Creating Dogs Creating Dogs d1 = Dog() d1.name = Alice d1.rabid = True d1.weight = 50.0 Memory d2 = Dog() d1 d2 rabid = True rabid = False weight = 50.0 weight = 0.0 name = Alice name =

  20. Creating Dogs Creating Dogs d1 = Dog() d1.name = Alice d1.rabid = True d1.weight = 50.0 Memory d2 = Dog() d2.name = Bob d1 d2 rabid = True rabid = False weight = 50.0 weight = 0.0 name = Alice name = Bob

  21. Creating Dogs Creating Dogs d1 = Dog() d1.name = Alice d1.rabid = True d1.weight = 50.0 Memory d2 = Dog() d2.name = Bob d2.weight = 30.0 d1 d2 rabid = True rabid = False weight = 50.0 weight = 30.0 name = Alice name = Bob

  22. Weve created 2 dogs! We ve created 2 dogs! Notice that they start with the same fields, and the same values in those fields. However, we edited the individual objects to hold data that was particular to that object Thus, accessing the fields from each object will give us different data: print(d1.name) # prints Alice print(d2.name) # prints Bob

  23. The . operator The . operator Dot operator used to Get to an instance s attributes Get to an instance s methods Basically, get inside the instance Format: <instance>.<attribute or method>

  24. Using the . operator Using the . operator d1 = Dog() d1.name = Alice d1.rabid = True d1.weight = 50.0 d2 = Dog() d2.name = Bob d2.weight = 30.0 d1.eat(2) d2.growl() d1.eat(4) d2.eat(-1) # Alice weighs 52 lbs # Bob says GRRRR # Alice weighs 56 lbs # Bob weighs 29 lbs

  25. The Constructor The Constructor This is a special method Used to give initial values to ALL attributes Is activated when someone creates an instance of the class (i.e.: creates an object) In most languages, the name of this method MUST be the same name as the class In Python, the name of this method must be __init__

  26. The Constructor The Constructor Dog with a constructor: class Dog: def __init__(self): self.rabid = False self.weight = 0.0 self.name = Dog without a constructor: class Dog: rabid = False weight = 0.0 name =

  27. The Constructor The Constructor Seems like extra work. Why initialize the fields inside the constructor instead of directly in the class body? Allows initializing the class fields in the constructor parameters Prevents unintended behavior when using mutable fields class Dog: def __init__(self, weight, rabid = False, name = ): self.rabid = rabid self.weight = weight self.name = name

  28. The Constructor The Constructor Initializing fields Initializing fields class Dog: def __init__(self, weight, rabid = False, name = ): # Dogs now need at least 1 argument before they can be # created: the weight d1 = Dog(45, name = Charlie ) self.rabid = rabid self.weight = weight self.name = name d1 rabid = False weight = 45 name = Charlie

  29. Designing the Constructor Designing the Constructor Constructors will vary, depending on design Ask questions: Are all Dogs born with the same rabid state? (yes they are all born non-rabid) Are all Dogs born with the same weight? (no they are born with different weights) Are all Dogs born with the same name? (no they all have different names) If ever no , then you need information passed in as parameters.

  30. The Constructor The Constructor Class vs Instance fields Class vs Instance fields Before we start talking about mutable fields, let s talk about the difference between class and instance fields Without the constructor, the Dog class looked like this: class Dog: rabid = False weight = 0.0 name =

  31. The Constructor The Constructor Class vs Instance fields Class vs Instance fields Even before we create our first Dog object, we already have one: The class itself. This allows us to change the default values of newly created objects d1 = Dog() # False, 0.0, Dog.rabid = True # Changed rabid for future Dogs Dog.weight = 200 # Changed weight for future Dogs d2 = Dog() # True, 200,

  32. The Constructor The Constructor Class vs Instance fields Class vs Instance fields When accessing a field using the class name, we say that field belongs to the class When accessing a field of a specific object, we say that field belongs to that instance (or object) In practice, what s actually happening is that a class field is shared across all newly created objects until an assignment is done After the first assignment operation, the object will have its own copy of the field

  33. The Constructor The Constructor What is actually happening What is actually happening class Dog: rabid = False weight = 0.0 name = Memory Dog rabid = False weight = 0.0 name =

  34. The Constructor The Constructor What is actually happening What is actually happening class Dog: rabid = False weight = 0.0 name = d1 = Dog() Memory Dog d1 rabid = False d1 has no fields. Its fields come from Dog weight = 0.0 name =

  35. The Constructor The Constructor What is actually happening What is actually happening class Dog: rabid = False weight = 0.0 name = d1 = Dog() # d1 now has its own # copy of rabid d1.rabid = True Memory Dog d1 rabid = False rabid = True weight = 0.0 name =

  36. The Constructor The Constructor What is actually happening What is actually happening Memory class Dog: rabid = False weight = 0.0 name = d1 = Dog() d1.rabid = True print(d1.weight) print(d1.rabid) Dog d1 rabid = False rabid = True weight = 0.0 name = # prints 0.0 # prints True

  37. The Constructor The Constructor What is actually happening What is actually happening Memory class Dog: rabid = False weight = 0.0 name = d1 = Dog() d1.rabid = True print(d1.weight) print(d1.rabid) d2 = Dog() Dog d1 rabid = False rabid = True weight = 0.0 name = d2

  38. The Constructor The Constructor What is actually happening What is actually happening Memory class Dog: d1 = Dog() d1.rabid = True print(d1.weight) print(d1.rabid) d2 = Dog() print(d2.rabid) # prints False Dog d1 rabid = False weight = 0.0 name = rabid = False rabid = True weight = 0.0 name = d2

  39. The Constructor The Constructor What is actually happening What is actually happening Memory class Dog: d1 = Dog() d1.rabid = True print(d1.weight) print(d1.rabid) d2 = Dog() print(d2.rabid) # prints False Dog.rabid = None Dog d1 rabid = False weight = 0.0 name = rabid = None rabid = True weight = 0.0 name = d2

  40. The Constructor The Constructor What is actually happening What is actually happening Memory class Dog: d1 = Dog() d1.rabid = True print(d1.weight) print(d1.rabid) d2 = Dog() print(d2.rabid) # prints False Dog.rabid = None print(d2.rabid) # prints None print(d1.rabid) # still prints True Dog d1 rabid = False weight = 0.0 name = rabid = None rabid = True weight = 0.0 name = d2

  41. The Constructor The Constructor Class vs Instance fields Class vs Instance fields To reiterate: when an object doesn t have a field, it will reach up to the Class fields. You can force an object to have its own fields by: Doing an assignment operation on the object s field d1.name = Alice Initializing the field in the constructor def __init__(self): self.name = Alice

  42. The Constructor The Constructor Mutable fields Mutable fields Normally, it makes no difference if an object has its own copy of the field or if it is using the classes field This is because the object will have its own copy once an assignment operation is done But this is a big problem for mutable fields (like lists)

  43. The Constructor The Constructor Mutable fields Mutable fields class Student: name = class Classroom: list_of_students = [] # the danger s1 = Student() s1.name = Alice s2 = Student() s2.name = Bob # all normal so far

  44. The Constructor The Constructor Mutable fields Mutable fields class Student: name = class Classroom: list_of_students = [] # the danger s1 = Student() s1.name = Alice s2 = Student() s2.name = Bob c1 = Classroom() # created a classroom c2 = Classroom() # created another classroom

  45. The Constructor The Constructor Mutable fields Mutable fields class Student: class Classroom: list_of_students = [] # the danger name = s1 = Student() s1.name = Alice s2 = Student() s2.name = Bob c1 = Classroom() # created a classroom c2 = Classroom() # created another classroom c1.list_of_students.append(s1) # added Alice to class 1 c2.list_of_students.append(s2) # added Bob to class 2

  46. The Constructor The Constructor Mutable fields class Student: name = class Classroom: list_of_students = [] # the danger Mutable fields s1 = Student() s1.name = Alice s2 = Student() s2.name = Bob c1 = Classroom() # created a classroom c2 = Classroom() # created another classroom c1.list_of_students.append(s1) # added Alice to class 1 c2.list_of_students.append(s2) # added Bob to class 2 print(c1) # prints [ Alice , Bob ] THIS IS A PROBLEM print(c2) # prints [ Alice , Bob ] BOTH CLASSROOMS ARE SHARING THE SAME STUDENTS

  47. The Constructor The Constructor Mutable fields Mutable fields What happened? Adding Alice to Classroom 1 added her to Classroom 2 and adding Bob to Classroom2 added him to Classroom 1 Why? Because the list_of_students field belongs to the class. Given that c1 and c2 don t have their individual copies, they are sharing the one from the class We never assigned a list_of_students field to c1 or c2, we appended information to it

  48. The Constructor The Constructor Mutable fields (solving the problem) Mutable fields (solving the problem) class Student: class Classroom: name = list_of_students = [] # the danger s1 = Student() s1.name = Alice s2 = Student() s2.name = Bob c1 = Classroom() # created a classroom c1.list_of_students = [] # c1 now has its own copy of list_of_students c2 = Classroom() # created another classroom c2.list_of_students = [] # c2 now has its own copy of list_of_students c1.list_of_students.append(s1) # added Alice to class 1 c2.list_of_students.append(s2) # added Bob to class 2 print(c1) # prints [ Alice ] Problem solved print(c2) # prints [ Bob ] Problem solved

  49. The Constructor The Constructor Mutable fields (solving the problem) Mutable fields (solving the problem) class Student: class Classroom: name = def __init__(self): self.list_of_students = [] # list created inside the constructor is now individual to every object s1 = Student() s1.name = Alice s2 = Student() s2.name = Bob c1 = Classroom() # created a classroom c2 = Classroom() # created another classroom c1.list_of_students.append(s1) # added Alice to class 1 c2.list_of_students.append(s2) # added Bob to class 2 print(c1) # prints [ Alice ] Problem solved print(c2) # prints [ Bob ] Problem solved

  50. Summary A class: has attributes (which are just variables) has a constructor which is used to initialize attributes has other methods (like eat and growl) is a blueprint (template) for creating objects creates a new data type An object: is an instance of a class has a state (variables) that is independent from others trying to access a variable that the object doesn t have prompts the object to reach to the class for that variable mutable fields at the class level need to be handled with care

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#