Jed Rembold
October 6, 2025
What would be the final value of c
printed in the code to the right?
def f(a, b=5, c=True):
if c:
return a + b
else:
return a * b
def g(c):
for i in range(2):
c+=b
return c > b
a = -3
b = 2
c = f(10, c=g(a))
print(c)
You can return any type of variable
from a function, including GObject graphical
objects
Can be useful to write simple functions that bundle together common tasks
For instance, to create a filled circle centered at some location:
def make_filled_circ(x_cent, y_cent, radius, color='black'):
circle = GOval( x_cent-radius, y_cent-radius,
2*radius, 2*radius)
circle.set_color(color)
circle.set_filled(True)
return circleimport so generally don’t want extraneous
print statements or to be running any code directlyimport the library in.py part of the extensionfrom pgl import GRect, GLabel
import random
def create_filled_rect(
x_cent, y_cent, width, height, fill_col='black', border_col=None
):
"""
Creates a GRect object with the desired fill color.
If a border color is specified, also draws the
border in the desired color.
"""
rect = GRect(x_cent-width/2, y_cent-height/2, width, height)
rect.set_filled(True)
if border_col is None:
rect.set_color(fill_col)
else:
rect.set_color(border_col)
rect.set_fill_color(fill_col)
return rect
def random_color():
"""
Returns a random opaque color as a hex string.
"""
color = "#"
for i in range(6):
color += random.choice("0123456789ABCDEF")
return color
def create_centered_label(x_cent, y_cent, text, font=None):
"""
Creates a GLabel object and centers it on the coordinates
x_cent and y_cent.
"""
label = GLabel(text)
if font is not None:
label.set_font(font)
label.set_location(x_cent - label.get_width() / 2,
y_cent + label.get_ascent() / 2 )
return label
(). Including the parentheses is how you
call the function!import math
def evaluate_numbers(func):
print(func)
print(func(0))
print(func(2))
print(func(10))
A = evaluate_numbers
A(math.sqrt)
A(math.exp)
Consider the code to the right.
a should
still exist when it is called!f2 must also keep track
of any local variables!b = 1
def f1(a):
print(a)
print(b)
def f2():
c = a + b
return c * 3
return f2
f2 = f1(10)
c = f2()
GWindow:|||gw|||.get_element_at(|||x|||,|||y|||) |
Returns the frontmost object at (x,y) or
None |
And more new methods that act on any
GObject
|||obj|||.set_location(|||x|||,|||y|||) |
Resets the location of the object to the specified point |
|||obj|||.move(|||dx|||,|||dy|||) |
Moves the object
|||dx||| and
|||dy||| pixels from its current
position |
|||obj|||.move_polar(|||dr|||,|||theta|||) |
Moves the object
|||dr||| pixel units in direction
|||theta||| |
|||obj|||.contains(|||x|||,|||y|||) |
Returns True
if the object contains the specified point |
|||obj|||.get_color() |
Returns the color currently assigned to the object |
Consider the simple program below, where we’ve imported the basics and some of our helper functions
def draw_dots():
def click_action(event):
c = create_filled_rect(
event.get_x(), event.get_y(),
10,10, random_color())
gw.add(c)
gw = GWindow(500, 500)
gw.add_event_listener("click", click_action)The click_action function specifies
what to do when the mouse is clicked
gw
variable since it is in the enclosing function and thus in the
closure.The last line of our example function:
gw.add_event_listener("click", click_action)
tells the graphics window (gw) to call
the click_action function whenever a mouse
“click” occurs within the window.
When the user clicks the mouse, the graphics window, in essense,
calls the client (your program) back to let it know that a click has
occured. Thus, functions such as
click_action are known as callback
functions.
The parameter event given to the
callback function is a special data structure called a mouse
event, which contains details about the specifics of the event that
triggered the action.
| Name | Description |
|---|---|
"click" |
The user clicks the mouse in the window |
"dblclk" |
The user double-clicks the mouse in the window |
"mousedown" |
The user presses the mouse button down |
"mouseup" |
The user releases the mouse button |
"mousemove" |
The user moves the mouse |
"drag" |
The user moves the mouse with the button down |
Certain actions can trigger more than one event
Events trigger no action unless the window is listening for that event
draw_dots()
function, you’ll notice that nothing happensYou can setup however many listeners you feel you need in order to make your program behave as desired
gw.add_event_listener("click", click_action)
gw.add_event_listener("dblclk", dblclk_action)from pgl import GWindow, GLine
WIDTH = 500
HEIGHT = 500
def draw_lines():
def mousedown_event(e):
x = e.get_x()
y = e.get_y()
line = GLine(x,y,x,y)
gw.add(line)
def drag_action(e):
line.set_end_point(e.get_x(), e.get_y())
gw = GWindow(WIDTH, HEIGHT)
line = None
gw.add_event_listener("mousedown", mousedown_event)
gw.add_event_listener("drag", drag_action)
if __name__ == '__main__':
draw_lines()
nonlocal
keyword, which allows you to state that a specific variable is
not local, but it tends to just confuse studentsGWindow object (mostly commonly
named gw)!gw objectgw.|||my_attribute_name||| = |||some_cool_value|||Just refer to the object and attribute name:
print(gw.|||my_attribute_name|||)from pgl import GWindow, GLine
WIDTH = 500
HEIGHT = 500
def draw_lines():
def mousedown_event(e):
x = e.get_x()
y = e.get_y()
gw.line = GLine(x,y,x,y)
gw.add(gw.line)
def drag_action(e):
gw.line.set_end_point(e.get_x(), e.get_y())
gw = GWindow(WIDTH, HEIGHT)
gw.line = None
gw.add_event_listener("mousedown", mousedown_event)
gw.add_event_listener("drag", drag_action)
if __name__ == '__main__':
draw_lines()