Jed Rembold
October 31, 2025
GRect class.
GRect classClass definitions in Python start with a header line consisting
of the keyword class and then the class
name
The body of the class will later contain definitions, but initially can just leave blank
pass keywordclass Employee:
"""This class is currently empty!"""Once the class is defined, you can create an object of this class type by calling the class as if it were a function:
clerk = Employee()You can select an attribute from an object by writing out the object name, followed by a dot and then the attribute name.
As an example
clerk.name
would select the name attribute for the
clerk object
Attributes are assignable, so
clerk.salary *= 2
would double the clerk’s current salary
You can create a new attribute in Python by simply assigning a name and a value, just like you’d define a new variable
We could, for instance, create a
clerk in the following fashion:
def create_clerk():
clerk = Employee()
clerk.name = "Bob Cratchit"
clerk.title = "clerk"
clerk.salary = 15
return clerkNote that none of these assigned attributes affect the
Employee class in any way: they are only
affecting the clerk object
We could accomplish this more generally by passing arguments to our function:
def create_employee(name, title, salary):
emp = Employee()
emp.name = name
emp.title = title
emp.salary = salary
return empWe could then use that as:
clerk = create_employee('Bob Cratchit', 'clerk', 15)
boss = create_employee(
'Ebeneezer Scrooge', 'founder', 1000
)Employee class called a
constructor, which is responsible for initializing attributes
of a newly created object
__init__selfselfselfs in the class with that object’s name
self is
doingself is always the
first parameter to the __init__ constructor
class Employee:
def __init__(self, name, title, salary):
self.name = namey
self.title = title
self.salary = salary
clerk = Employee('Bob Cratchit', 'clerk', 15)
self when creating the object, Python
supplies this reference automaticallyWhat is printed out on the final line of code to the right?
Honda red 2006Honda blue 2006Toyota blue 2008Honda red 2008class Car:
def __init__(self, color, year):
self.color = color
self.year = year
self.make = 'Toyota'
A = Car('blue', 2008)
A.make = 'Honda'
B = Car('red', 2006)
A.year = B.year
print(A.make, A.color, A.year)
Most classes define additional functions called methods to allow clients to read or update attributes or manipulate the object
Methods look like a normal function definition but will
always declare the parameter
self at the beginning of the parameter
list
Methods are defined in the body of the class and would thus look something like:
def |||method name||| (self, |||other parameters|||):
|||...body of the method...|||For example
def give_raise(self, amount):
self.salary += amountPython sets self to be a reference to
the receiver, which is the object to which the method is
applied (the object that comes before the dot)
clerk = Employee('Bob', 'clerk', 15)
clerk.give_raise(15)You retrieve the method from the class itself, and then provide
self manually, where
self is the object you want to act on
clerk = Employee('Bob', 'clerk', 15)
Employee.give_raise(clerk, 15)
In the abstraction boundary model, the client is not supposed to muck-about with the object internals
The implementation should therefore provide methods to retrieve desired attributes (called getters) or to make changes to desired attributes (called setters)
Setting up getters and setters for the attribute
salary might look like:
def get_salary(self):
return self.salary
def set_salary(self, new_salary):
self.salary = new_salaryGetters are far more common than setters, as you don’t always want the client to have the freedom to change attributes on a whim
Printing out an object that you just created as an instance of a custom class will look ugly:
>>> C = Employee('Bob', 'clerk', 15)
>>> print(C)
<__main__.Employee object at 0x7f942ba13550>You can define special methods for a class that specify how your object should be converted to a string (or anything else really)
__str__ or
__repr__ method to specify how your object
should be printed
class Employee:
def __init__(self, name, title, salary):
self.name = name
self.title = title
self.salary = salary
def __str__(self):
return f"{self.name} ({self.title}): {self.salary}"
def get_salary(self):
return self.salary
def set_salary(self, new_salary):
self.salary = new_salary
from pgl import GWindow, GOval, GRect
import random
GW_WIDTH = 500
GW_HEIGHT = 500
def random_color():
color = "#"
for _ in range(6):
color += random.choice("0123456789ABCDEF")
return color
class Firework:
""" Creates a new firework with initial flight and then
explosion.
"""
def __init__(self, size):
self.obj = GOval(GW_WIDTH/2, GW_HEIGHT, size, size)
self.obj.set_filled(True)
self.obj.set_color("white")
self.speed = 5
self.heading = random.randint(60,120)
self.fuse = random.randint(50,100)
self.maxsize = random.randint(60,100)
self.color = random_color()
self.mode = 0
def get_object(self):
""" Returns the firework graphical object. """
return self.obj
def should_terminate(self):
""" Checks if the firework should be removed. """
return self.mode > 1
def move(self):
""" Moves the firework in its initial flight. """
self.obj.move_polar(self.speed, self.heading)
self.fuse -= 1
if self.fuse < 0:
self.mode += 1
self.obj.set_color(self.color)
def explode(self):
""" Grows the firework explosion upon detonation. """
R = 2
x = self.obj.get_x()
y = self.obj.get_y()
S = self.obj.get_width()
self.obj.set_bounds(x-R/2, y-R/2, S+R, S+R)
if self.obj.get_width() >= self.maxsize:
self.mode += 1
def update(self):
""" Controls what the firework should be doing during
each stage.
"""
if self.mode == 0:
self.move()
elif self.mode == 1:
self.explode()
def fireworks_show():
""" Makes a fireworks show! """
def step():
""" Calls up update method on all fireworks in the box
and removes if necessary.
"""
for f in firework_box[:]:
f.update()
if f.should_terminate():
gw.remove(f.get_object())
firework_box.remove(f)
def give_me_more_fireworks():
""" Adds more fireworks to the box. """
new = Firework(2)
firework_box.append(new)
gw.add(new.get_object())
gw = GWindow(GW_WIDTH, GW_HEIGHT)
sky = GRect(GW_WIDTH, GW_HEIGHT)
sky.set_filled(True)
gw.add(sky)
firework_box = []
gw.set_interval(step, 20)
gw.set_interval(give_me_more_fireworks, 100)
if __name__ == '__main__':
fireworks_show()