Classes and objects
โ Report an issue with this lessonA class is a blueprint. An object (instance) is one specific thing built from that blueprint.
class Course:
def __init__(self, title, price):
self.title = title
self.price = price
def describe(self):
return f"{self.title} -- ${self.price}"
html_course = Course("HTML Fundamentals", 29.99)
print(html_course.describe()) # HTML Fundamentals -- $29.99
__init__ runs when you create an object and sets up its
starting state. self refers to the specific object the method
was called on โ every method that touches instance data takes
self as its first parameter.
Each call to Course(...) creates a completely independent
object with its own copy of the attributes set inside
__init__. Two Course instances never share
title or price unless you explicitly make one
point at the other:
c1 = Course("HTML Fundamentals", 29.99)
c2 = Course("SQL Databases", 59.99)
c1.price = 19.99 # only changes c1
print(c2.price) # still 59.99 -- completely separate object
This is different from a class-level attribute โ one defined directly in the class body, outside any method โ which is shared across every instance until an individual instance overrides it:
class Course:
platform = "Coding Prodigies" # shared by every Course instance
def __init__(self, title, price):
self.title = title # unique to each instance
self.price = price
c1 = Course("HTML", 29.99)
c2 = Course("SQL", 59.99)
print(c1.platform) # "Coding Prodigies"
print(c2.platform) # "Coding Prodigies" -- same value, same class attribute
A common mistake for anyone coming from another language is forgetting
self โ either leaving it off a method's parameter list
(Python then passes the instance as the first positional argument anyway,
silently binding it to whatever you named first, which produces confusing
errors), or forgetting to write self. before an attribute
inside a method, which creates a plain local variable that disappears when
the method returns instead of actually updating the object:
class Course:
def __init__(self, title, price):
self.title = title
self.price = price
def apply_discount(self, percent):
price = self.price * (1 - percent / 100) # BUG: local variable, not saved
# should be: self.price = self.price * (1 - percent / 100)
Calling apply_discount(10) above looks like it worked โ
no error, no crash โ but course.price is completely
unchanged afterward, because price without self.
is just a throwaway local name. This is one of the most common silent bugs
in early object-oriented Python code, precisely because nothing about it
raises an exception.
Try it yourself
HTML Fundamentals -- $29.99
Run your code and get it working before marking this lesson complete.
8 more lessons โ including Project: build a small shape library โ plus a certificate are waiting.
Unlock the full course โ $59.99