1 of 48

Scope and

Pass By Reference

Jake Shoudy

Oct 28, 2022

CSCI 110 - Lecture 27

2 of 48

Announcements

3 of 48

Project 2: Part 2

More search engine things using 2D Lists :)

Due Sunday October 30th at 11:59pm

4 of 48

Project 1: Part 5 (Optional)

Multiplayer blackjack and score keeping.

Earn up to 50 points back on project 1 or 12.5 points on midterm 1.

Show Jake your code in person for grading

Due Monday October 31st

5 of 48

Final Exam Date?

  • Section 2 (MWF: 8-9am) will have their final exam on Friday December 2nd from 8-10am
  • Section 1 (MWF: 11am-12) will have their final exam on Monday December 5th from 10:30am-12:30
  • Section 3 (MWF: 3-4pm) will have their final exam on Tuesday December 6th from 3:30-5:30pm.

OR

Everyone takes the test on Tuesday 11/29

Please vote on Ed ASAP

6 of 48

7 of 48

Recap

8 of 48

Review: Functions

def example_function(foo, bar, baz):

print(foo)

print(bar)

print(baz)

return foo

example_function("example", "text", "stuff")

9 of 48

Program: Max

Function: max()

Input: two numbers

Output: bigger of the two numbers

Examples:

max(1, 100) -> 100

max(-100, 0) -> 0

10 of 48

Calling Functions

result = get_max(1, 2)

other_result = get_max(-5, 5)

def get_max(a, b):

if a > b:

answer = a

else:

answer = b

return answer

Wasn’t defined yet!

NameError: name 'get_max' is not defined

11 of 48

Calling Functions

def max(a, b):

if a > b:

answer = a

else:

answer = b

return answer

result = max(1, 2)

other_result = max(-5, 5)

Call function to make it run.

Function definition must come before calling the function.

12 of 48

Flow of Execution

Order that code is run

13 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

14 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Instructions are set up but have not been called yet, so this doesn't print.

15 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Prints “yellow”

16 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Calls the function!

17 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Function has been called! JUMP to function definition and execute code.

18 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Prints “blue”

19 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Once function is done, go back to where function was called, and continue.

20 of 48

Flow of Execution

def aFunction():

print("blue")

print("yellow")

aFunction()

print("green")

Prints “green”

21 of 48

Variable Scope

22 of 48

Scope

def wish_happy_birthday(name):

message = 'Happy birthday ' + name + '!'

return message

first_name = 'Mr Jake'

greeting = wish_happy_birthday(first_name)

print(greeting)

Happy birthday Mr Jake!

23 of 48

Scope

def wish_happy_birthday(name):

message = 'Happy birthday ' + name + '!'

return message

first_name = 'Mr Jake'

print(message)

greeting = wish_happy_birthday(first_name)

print(greeting)

NameError: name 'message' is not defined

24 of 48

Scope

def wish_happy_birthday(name):

message = 'Happy birthday ' + name + '!'

return message

first_name = 'Mr Jake'

greeting = wish_happy_birthday(first_name)

print(message)

print(greeting)

NameError: name 'message' is not defined

25 of 48

Scope

Where a variable is “visible”

2 types of scope:

global: can be used anywhere

local: can only be used in block of code where variable is defined

Parameters and variables defined in functions have local scope

When variable names are duplicated, look inside of the local scope first!

26 of 48

Scope Island

name

first_name

greeting

message

wish_happy_birthday

return

local

global

parameters

arguments

return value

27 of 48

Scope

def wish_happy_birthday(name):

message = 'Happy birthday ' + first_name + '!'

return message

first_name = 'Mr Jake'

greeting = wish_happy_birthday('Darth Vader')

print(greeting)

Happy birthday Mr Jake!

28 of 48

Scope

def wish_happy_birthday(name):

first_name = 'Mr Shoudy'

message = 'Happy birthday ' + first_name + '!'

return message

first_name = 'Mr Jake'

greeting = wish_happy_birthday('Darth Vader')

print(greeting)

Happy birthday Mr Shoudy!

29 of 48

Scope

def wish_happy_birthday(name):

message = 'Happy birthday ' + first_name + '!'

first_name = 'Mr Shoudy'

return message

first_name = 'Mr Jake'

greeting = wish_happy_birthday('Darth Vader')

print(greeting)

UnboundLocalError: local variable 'first_name' referenced before assignment

30 of 48

Local: Variables and Parameters

def addTwo(num):

num = num + 2

print("Inside the function, num = " + str(num))

return num

num = 8

print("Before the function, num = " + str(num))

new_num = addTwo(num)

print("After the function, num = " + str(num))

Before the function, num = 8

Inside the function, num = 10

After the function, num = 8

31 of 48

Pass by Value vs

Pass by Reference

32 of 48

Pass By Value vs Pass By Reference

Pass variable to function

Two ways of how computer actually passes information to function: pass by value and pass by reference.

33 of 48

Pass By Value

pass by value: make copy of value inside variable and pass that to function

Any operations inside function definition do not modify original variable

34 of 48

Pass By Value: Examples

def add_two(num):

num = num + 2

return num

digit = 5

result = add_two(digit)

print(result)

print(digit)

def add_world(phrase):

phrase = phrase + 'world'

return phrase

word = 'hello'

result = add_world(word)

print(result)

print(word)

7

5

helloworld

hello

35 of 48

Pass By Reference

pass by reference: pass pointer (place in computer memory) of variable to function

Any operations inside function definition do modify original variable

In Python, the variable type determines whether the argument will be pass-by-reference or pass-by-value:

  • Immutable types are always pass-by-value
    • Ints, Floats, Strings, Booleans, Tuples
  • Mutable types are always pass-by-reference
    • Lists, Sets, Dictionaries

36 of 48

Pointers

A pointer is a place in memory. In PythonTutor, they are represented by an arrow.

The variable (numbers) tells you where to find the list in memory.

37 of 48

Pass By Reference: List Examples

[1, 2, 3, 4, 2]

[1, 2, 3, 4, 2]

def add_two(nums):

nums.append(2)

return nums

numbers = [1, 2, 3, 4]

result = add_two(numbers)

print(result)

print(numbers)

def remove_two(nums):

nums.pop(2)

return nums

numbers = [1, 2, 3, 4]

result = remove_two(numbers)

print(result)

print(numbers)

[1, 3, 4]

[1, 3, 4]

38 of 48

Pass By Reference: Dictionary Examples

{'a': 3, 'b': 1, 'c': 2}

{'a': 3, 'b': 1, 'c': 2}

{'a': 3, 'b': 1}

{'a': 3, 'b': 1}

def add_c(mapping):

mapping['c'] = 2

return mapping

count = {'a': 3, 'b': 1}

result = add_c(count)

print(result)

print(count)

def remove_c(mapping):

mapping.pop('c')

return mapping

count = {'a': 3, 'b': 1, 'c': 2}

result = remove_two(count)

print(result)

print(count)

39 of 48

Why does Pass-by-Reference Exist?

Why does this distinction exist? Why isn’t everything pass-by-value?

This is because lists, sets, dictionaries, and other mutable types can be large (thousands of elements), so it would be very expensive for the computer to make copies of them every time a function is called.

40 of 48

Pass By Reference: void functions

Pass by reference makes it possible to write void functions* that take a list or a dictionary as argument

Function has side effect: mutate list passed in as argument - but does not return value

* void functions are just functions that do not return (or explicitly return None)

41 of 48

Void Functions: List Example

[1, 2, 3, 4, 2]

[1, 2, 3, 4, 2]

def add_two(nums):

nums.append(2)

return nums

numbers = [1, 2, 3, 4]

result = add_two(numbers)

print(numbers)

def add_two(nums):

nums.append(2)

numbers = [1, 2, 3, 4]

add_two(numbers)

print(numbers)

42 of 48

Void Functions: Dictionary Example

{'a': 3, 'b': 1}

{'a': 3, 'b': 1}

def remove_c(mapping):

mapping.pop('c')

return mapping

count = {'a': 3, 'b': 1, 'c': 2}

result = remove_two(count)

print(count)

def remove_c(mapping):

mapping.pop('c')

count = {'a': 3, 'b': 1, 'c': 2}

remove_two(count)

print(count)

43 of 48

Void Functions: Dictionary Example

None

def remove_c(mapping):

mapping.pop('c')

count = {'a': 3, 'b': 1, 'c': 2}

count = remove_c(count)

print(count)

44 of 48

Pass By Value vs

Pass By Reference

pass by value: passes a copy of the value the function

Modifying the parameter DOES NOT modify the argument

Default behavior for immutable types

pass by reference: passes a pointer to the object to the function

Modifying the parameter DOES modify the argument

Default behavior for mutable types

45 of 48

What if don’t want to change original?

def add_two(nums):

nums.extend([2, 5])

return nums

numbers = [1, 2, 3, 4]

result = add_two(numbers)

print(result)

print(numbers)

def add_two(nums):

nums_copy = nums.copy()

nums_copy.extend([2, 5])

return nums_copy

numbers = [1, 2, 3, 4]

result = add_two(numbers)

print(result)

print(numbers)

46 of 48

What if don’t want to change original?

def double_value(mapping):

for item in mapping:

mapping[item] *= 2

return mapping

count = {'a': 3, 'b': 1}

result = double_value(count)

print(result)

print(count)

def double_value(mapping):

mapping_copy = mapping.copy()

for item in mapping_copy:

mapping_copy[item] *= 2

return mapping_copy

count = {'a': 3, 'b': 1}

result = double_value(count)

print(result)

print(count)

47 of 48

Lists: + vs +=

Won’t be tested on this - but probably good to know for writing Python code

def add_ten(nums):

nums = nums + [10]

return nums

numbers = [1, 2, 3]

result = add_ten(numbers)

print(result)

print(numbers)

def add_ten(nums):

nums += [10]

return nums

numbers = [1, 2, 3]

result = add_ten(numbers)

print(result)

print(numbers)

[1, 2, 3, 10]

[1, 2, 3]

[1, 2, 3, 10]

[1, 2, 3, 10]

48 of 48

Let’s Code!