Computer Science

To start this guide, download this zip file.

Functions that mutate

A function takes one or more parameters. Some functions will mutate or change their parameters. For example, a function may take a list as a parameter, and then append or remove things from the list, or change items in the list.

In general, when you write a function, it is a good idea to avoid mutating the parameters you are given. Let’s walk through a few examples

Replacing 2 with 5

Here is a function that mutates a list — it replaces every 2 with a 5. You can find this code in `replace_mutate.py`:

``````def replace_two_with_five(items):
"""
Replace every 2 with a 5. Modify the list in place.
"""
for i in range(len(items)):
if items[i] == 2:
items[i] = 5

if __name__ == '__main__':
numbers = [1, 2, 3, 2]
print("original list:")
print(numbers)
print()
replace_two_with_five(numbers)
print("original list:")
print(numbers)``````

This will print:

``````original list:
[1, 2, 3, 2]

original list:
[1, 5, 3, 5]``````

It is generally preferred to write functions that do NOT mutate their inputs. Whenever possible, try to write functions that don’t mutate.

A version that does not mutate the list

For example, this code will also replace every 2 with a 5, but it returns a new list instead of modifying the original list. You can find this code in `replace_without_mutate.py`:

``````def replace_two_with_five(items):
"""
Replace every 2 with a 5. Modify the list in place.
"""
new_items = []
for item in items:
if item == 2:
item = 5
new_items.append(item)
return new_items

if __name__ == '__main__':
numbers = [1, 2, 3, 2]
print("original list:")
print(numbers)
print()
new_numbers = replace_two_with_five(numbers)
print("original list:")
print(numbers)
print()
print("new list:")
print(new_numbers)``````

This will print:

``````original list:
[1, 2, 3, 2]

original list:
[1, 2, 3, 2]

new list:
[1, 5, 3, 5]``````

Notice how the original list is unchanged.

Be sure to document whether your function mutates its inputs or not. Write non-mutating functions whenever possible.

Editing words in a phrase

To show you another example of list indexing, here is a small program that replaces words in a phrase. The program works like this:

• a person enters a phrase, containing multiple words (“hello I am pleased to meet you”)
• the program loops for as long as you want
• enter a word (“pleased”)
• enter a replacement word (“thrilled”)
• replace the word with its replacement in the phrase (replace “pleased” with “thrilled” in the phrase)

Here is code to do this, which is in `edits.py`:

``````def replace_word(phrase, word, other):
"""
<phrase> should be a list that contains multiple words
<word> and <other> are words

Replace <word> with <other> in <phrase>.
This modifies the list in <phrase>.
"""
for i in range(len(phrase)):
if phrase[i] == word:
phrase[i] = other

def main():
# ask for a phrase (multiple words)
# spilt it into a list of words
phrase = input('Phrase: ').split()
print(phrase)

# ask for a series of <word>s and <replacement>s
# replace each instance of <word> with its <replacement> in the
# phrase
while True:
word = input('Word: ')
if not word:
break
other = input('Replacement: ')
replace_word(phrase, word, other)
print(phrase)

# turn the list of words back into a string
print(' '.join(phrase))

if __name__ == '__main__':
main()``````

Some things to note:

• The `replace_word()` function modifies — or mutates — the list it is given. It does not return a new list.

• One of the most common ways you will use `range()` is to loop through all of the items in a list. You can do this by giving `range()` the length of the list:

``for i in range(len(phrase)):``

If you run this code, you can do something like this:

``````Phrase: You are doing great with this stuff
['You', 'are', 'doing', 'great', 'with', 'this', 'stuff']
Word: great
Replacement: awesome
['You', 'are', 'doing', 'awesome', 'with', 'this', 'stuff']
Word: stuff
Replacement: class
['You', 'are', 'doing', 'awesome', 'with', 'this', 'class']
Word:
You are doing awesome with this class``````

Notice how we have put an extra `print()` statement in the code so you can see how the list is being modified each time through the loop.

Scoreboard

We are going to write a game for two teams that has these rules:

• the computer picks a secret number between 1 and 10
• both teams try to guess the secret number
• the team that is closer to the secret gets a point
• if both teams are equally close, they both get a point
• the first team to five points wins

To represent points, we are going to use two emojis:

``````POINT = '🟩'
NO_POINT = '⬜️'``````

To represent how many points each team has earned so far, we are going to use a list. This list means a team has scored zero points so far:

``['⬜️', '⬜️', '⬜️', '⬜️', '⬜️']``

ad this list means a team has scored three points so far:

``['🟩', '🟩', '🟩', '⬜️', '⬜️']``

Here is a flow chart for this problem:

We can also write this in English:

• create score lists for each team
• while True
• pick a secret number
• get guesses for each team
• add a point for the team that wins (or both if there is a tie)
• if Team 1 has five points
• Team 1 wins!
• break
• if Team 2 has five points
• Team 2 wins!
• break

(You may notice a small issue with this code. If both teams make it to five points simultaneously, Team 1 wins. With some extra `if` statements you could fix this.)

Here is the code that implements these ideas, which you can find in `scoreboard.py`:

``````import random

# these are two variables that represent a point and no point
# since the variable names are in uppercase, we know we should
# never change them
POINT = '🟩'
NO_POINT = '⬜️'

"""
<scores> is a list of POINT and NO_POINT characters

Change the first NO_POINT in the list to POINT

Modifies the <scores> list.
"""
# loop through all of the characters in <scores>
for i in range(len(scores)):
# if this character is NO_POINT, change it to
# POINT and return
if scores[i] == NO_POINT:
scores[i] = POINT
return

def main():
# create a list of 5 NO_POINT characters, representing
# give empty
# each list will look like this:
# ['⬜️', '⬜️', '⬜️', '⬜️', '⬜️']
team1_score = [NO_POINT] * 5
team2_score = [NO_POINT] * 5

while True:
# choose a random number between 1 and 10
secret = random.randint(1, 10)
# decide which team goes first using a random number
# between 0 and 1. 50% of the time team 1 will go first,
# and 50% of teh time team 2 will go first
if random.random() < 0.5:
team1_guess = int(input('Team 1 guess: '))
team2_guess = int(input('Team 2 guess: '))
else:
team2_guess = int(input('Team 2 guess: '))
team1_guess = int(input('Team 1 guess: '))

print(f"The secret number was {secret}")

# calculate how far off each team was
diff1 = abs(team1_guess - secret)
diff2 = abs(team2_guess - secret)

if diff1 < diff2:
# if team 1 was closer, they get a point
elif diff2 < diff1:
# if team 2 was closer, they get a point
else:
# if both teams were equally close, they both get a point

# print the scores
print(f'Team 1: {team1_score}')
print(f'Team 2: {team2_score}')

# first team to five points wins
# we can check if a team has five points by checking if
# the last character in the list is equal to POINT
if team1_score[-1] == POINT:
print('Team 1 wins!')
break

if team2_score[-1] == POINT:
print('Team 2 wins!')
break

if __name__ == '__main__':
main()``````

If you run this code, you should see something like this:

``````Team 2 guess: 5
Team 1 guess: 4
The secret number was 8
Team 1: ['⬜️', '⬜️', '⬜️', '⬜️', '⬜️']
Team 2: ['🟩', '⬜️', '⬜️', '⬜️', '⬜️']
Team 2 guess: 7
Team 1 guess: 6
The secret number was 9
Team 1: ['⬜️', '⬜️', '⬜️', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '⬜️', '⬜️', '⬜️']
Team 1 guess: 3
Team 2 guess: 4
The secret number was 5
Team 1: ['⬜️', '⬜️', '⬜️', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '🟩', '⬜️', '⬜️']
Team 2 guess: 8
Team 1 guess: 7
The secret number was 10
Team 1: ['⬜️', '⬜️', '⬜️', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '🟩', '🟩', '⬜️']
Team 2 guess: 5
Team 1 guess: 6
The secret number was 6
Team 1: ['🟩', '⬜️', '⬜️', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '🟩', '🟩', '⬜️']
Team 1 guess: 5
Team 2 guess: 4
The secret number was 5
Team 1: ['🟩', '🟩', '⬜️', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '🟩', '🟩', '⬜️']
Team 2 guess: 5
Team 1 guess: 6
The secret number was 10
Team 1: ['🟩', '🟩', '🟩', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '🟩', '🟩', '⬜️']
Team 2 guess: 3
Team 1 guess: 4
The secret number was 1
Team 1: ['🟩', '🟩', '🟩', '⬜️', '⬜️']
Team 2: ['🟩', '🟩', '🟩', '🟩', '🟩']
Team 2 wins!``````