+ - 0:00:00
Notes for current slide
Notes for next slide

Lecture 14


DANL 100: Programming for Data Analytics

Byeong-Hak Choe

October 18, 2022

1 / 39

Dictionaries and Sets


2 / 39

Dictionaries

  • A dictionary is similar to a list, but the order of items doesn't matter, and they aren't selected by an offset such as 0 or 1.

    • Instead, we specify a unique key to associate with each value.

    • This key is often a string, but it can actually be any of Python's immutable types: boolean, integer, float, tuple, string, and others.

  • Dictionaries are mutable, so we can add, delete, and change their key-value elements.

3 / 39

Dictionaries

Create with {}

  • To create a dictionary, we place curly brackets ({}) around comma-separated key : value pairs.
empty_dict = {}
empty_dict

Let's make a small dictionary with quotes from Ambrose Bierce's The Devil's Dictionary:

bierce = {"day": "A period of twenty-four hours, mostly misspent",
"positive": "Mistaken at the top of one's voice",
"misfortune": "The kind of fortune that never misses"}
bierce
4 / 39

Dictionaries

Create with dict()

  • We can also create a dictionary by passing named arguments and values to the dict() function.
acme_customer = {'first': 'Wile', 'middle': 'E', 'last': 'Coyote'}
acme_customer
acme_customer = dict(first = "Wile", middle = "E", last = "Coyote")
acme_customer
  • The argument names in dict() need to be legal variable names (no spaces, no reserved words):
x = dict(name="Elmer", def="hunter")
5 / 39

Dictionaries

Convert with dict()

  • We can use dict() to convert two-value sequences into a dictionary.
    • We might run into such key-value sequences at times, such as "Geneseo, 20, Brockport, 14."
    • The first item in each sequence is used as the key and the second as the value.
  • lol (a list of two-item lists):
lol = [ ['a', 'b'], ['c', 'd'], ['e', 'f'] ]
dict(lol)
  • lot (a list of two-item tuples):
lot = [ ('a', 'b'), ('c', 'd'), ('e', 'f') ]
dict(lot)
  • tol (a tuple of two-item lists):
tol = ( ['a', 'b'], ['c', 'd'], ['e', 'f'] )
dict(tol)
  • los (a list of two-character strings):
los = [ 'ab', 'cd', 'ef' ]
dict(los)
  • tos (a tuple of two-character strings):
tos = ( 'ab', 'cd', 'ef' )
dict(tos)
6 / 39

Dictionaries

Add or Change an Item by [ key ]

  • Adding an item to a dictionary is not complicated.

    • Just refer to the item by its key and assign a value.

    • If the key was already present in the dictionary, the existing value is replaced by the new one.

    • If the key is new, it's added to the dictionary with its value.

7 / 39

Dictionaries

Add or Change an Item by [ key ]

  • Let's make a dictionary of some pairs of US cities and states, using their states as keys and city names as values:
st_city = {
'MN': 'Rochester',
'WY': 'Laramie',
'CO': 'Denver'
}
st_city
  • Here, we want to add Rochester, NY.
    • Here's an attempt to add it, but it spelled wrong:
st_city['NY'] = 'Rocjester'
st_city
  • Here's some repair code:
st_city['NY'] = 'Rochester'
st_city
  • Remember that dictionary keys must be unique.
    • That's why we used state names for keys instead of city names.
    • If we use a key more than once, the last value wins:
city_st = {
'Rochester': 'MN',
'Laramie': 'WY',
'Denver': 'CO',
'Rochester': 'NY'
}
city_st
8 / 39

Dictionaries

Get an Item by [key] or with get()

  • We specify the dictionary and key to get the corresponding value:
city_st = {
'Rochester': 'MN',
'Laramie': 'WY',
'Denver': 'CO',
'Rochester': 'NY'
}
city_st['Denver']
  • If the key is not present in the dictionary, we'll get an exception:
city_st['Buffalo']
  • There are two good ways to avoid this: in and get()
  • Test for the key at the outset by using in:
'Buffalo' in city_st
  • Use the special dictionary get() function.
    • If the key exists, we get its value:
city_st.get('Denver')
  • Use the special dictionary get() function.
    • If the key does not exist and the optional value is provided, we get the optional value:
city_st.get('Buffalo', 'Not in city_st')
  • Use the special dictionary get() function.
    • If the key does not exist and the optional value is not provided, we get None, which displays nothing in the console.
city_st.get('Buffalo')
9 / 39

Dictionaries

Get All Keys with keys()

  • We can use keys() to get all of the keys in a dictionary.
signals = {'green': 'go',
'yellow': 'go faster',
'red': 'smile for the camera'}
signals.keys()
list( signals.keys() ) # to turn the result into a list object.

Get All Values with values()

  • To obtain all the values in a dictionary, use values():
signals = {'green': 'go',
'yellow': 'go faster',
'red': 'smile for the camera'}
signals.values()
list( signals.values() ) # to turn the result into a list object.

Get All Key-Value Pairs with items()

  • When we want to get all the key-value pairs from a dictionary, use the items() function:
signals = {'green': 'go',
'yellow': 'go faster',
'red': 'smile for the camera'}
signals.items()
list( signals.items() ) # to turn the result into a list object.

Get Length with len()

  • Count your key-value pairs:
signals = {'green': 'go',
'yellow': 'go faster',
'red': 'smile for the camera'}
len(signals)

Combine Dictionaries with {**a, **b}

  • Starting with Python 3.5, there's a new way to merge dictionaries, using the **:
first = {'a': 'agony', 'b': 'bliss'}
second = {'b': 'bagels', 'c': 'candy'}
{**first, **second}
third = {'d': 'donuts'}
{**first, **third, **second}

Combine Dictionaries with update()

  • We can use the update() function to copy the keys and values of one dictionary into another.
    • Let's update st_city with other_city
st_city = { 'MN': 'Rochester',
'WY': 'Laramie',
'CO': 'Denver',
'NY': 'Rochester' }
other_city = {'MA': 'Boston'}
st_city.update(other_city)

Combine Dictionaries with update()

  • What happens if the second dictionary has the same key as the dictionary into which it's being merged?
first = {'a': 1, 'b': 2}
second = {'b': 'platypus'}
first.update(second)
first
10 / 39

Dictionaries

Delete an Item by Key with del

  • We can delete an item in a dictionary with del:
del st_city['NY']
st_city

Get an Item by Key and Delete It with pop()

  • pop() combines get() and del.
    • If we give pop() a key and it exists in the dictionary, it returns the matching value and deletes the key-value pair.
    • If the key doesn't exist but we give pop() a second default argument, all is well and the dictionary is not changed:
len(st_city)
st_city.pop('MN') # Check len(st_city)
st_city.pop('MN') # If it doesn't exist, it raises an exception:
st_city.pop('MN', 'Not exist')

Delete All Items with clear()

  • To delete all keys and values from a dictionary, use clear() or just reassign an empty dictionary ({}) to the name:
st_city.clear()
st_city
st_city = { 'MN': 'Rochester',
'WY': 'Laramie',
'CO': 'Denver',
'NY': 'Rochester' }
st_city = {}
st_city

Test for a Key with in

  • If we want to know whether a key exists in a dictionary, use in:
st_city = { 'MN': 'Rochester',
'WY': 'Laramie',
'CO': 'Denver',
'NY': 'Rochester' }
'NY' in st_city
'WY' in st_city
'CA' in st_city

Assign with =

  • If we make a change to a dictionary, it will be reflected in all the names that refer to it:
signals = { 'green': 'go',
'yellow': 'go faster',
'red': 'smile for the camera' }
save_signals = signals
signals['blue'] = 'confuse everyone'
signals
  • What are in save_signals now?

Copy with copy()

  • To actually copy keys and values from a dictionary to another dictionary and avoid this, we can use copy():
signals = { 'green': 'go',
'yellow': 'go faster',
'red': 'smile for the camera' }
original_signals = signals.copy()
signals['blue'] = 'confuse everyone'
signals
  • What are in original_signals now?

Copy Everything with deepcopy()

  • Suppose that the value for red in signals was a list instead of a single string:
signals = { 'green': 'go',
'yellow': 'go faster',
'red': ['stop', 'smile'] }
signals_copy = signals.copy()
signals
  • What are in signals_copy?

Copy Everything with deepcopy()

  • Let's change one of the values in the red list:
signals = { 'green': 'go',
'yellow': 'go faster',
'red': ['stop', 'smile'] }
signals_copy = signals.copy()
signals['red'][1] = 'sweat'
signals
  • What are in signals_copy?

Copy Everything with deepcopy()

  • To avoid this, we can use deepcopy():
import copy
signals = { 'green': 'go',
'yellow': 'go faster',
'red': ['stop', 'smile'] }
signals_deepcopy = copy.deepcopy(signals)
signals
signals_deepcopy
signals['red'][1] = 'sweat'
signals
  • What are in signals_deepcopy?
11 / 39

Dictionaries

Compare Dictionaries

  • Much like lists and tuples, dictionaries can be compared with the simple comparison operators == and !=:
a = {1:1, 2:2, 3:3}
b = {3:3, 1:1, 2:2}
a == b
a != b
a <= b # does it work?

Iterate with for and in

  • Iterating over a dictionary (or its keys() function) returns the keys.
accusation = {'room': 'ballroom',
'weapon': 'lead pipe',
'person': 'Col. Mustard'}
for card in accusation: # or, for card in accusation.keys():
print(card)

Iterate with for and in

  • To iterate over the values rather than the keys, we use the dictionary's values() function:
accusation = {'room': 'ballroom',
'weapon': 'lead pipe',
'person': 'Col. Mustard'}
for value in accusation.values():
print(value)

Iterate with for and in

  • To return both the key and value as a tuple, we can use the items() function:
accusation = {'room': 'ballroom',
'weapon': 'lead pipe',
'person': 'Col. Mustard'}
for item in accusation.items():
print(item)

Iterate with for and in

  • For each tuple returned by items(), let's assign the first value (the key) to card, and the second (the value) to contents:
accusation = {'room': 'ballroom',
'weapon': 'lead pipe',
'person': 'Col. Mustard'}
for card, contents in accusation.items():
print('Card', card, 'has the contents', contents)

Dictionary Comprehensions

  • Dictionaries also have comprehensions.
    • The simplest form of dictionary comprehension looks like this:

Dictionary Comprehensions

  • Let's run a loop over each of the seven letters in the string 'letters' and counting how many times that letter appears.
word = 'letters'
letter_counts = {letter: word.count(letter) for letter in word}
letter_counts
  • How many times do we count 't' here?

Dictionary Comprehensions

  • Let's run a loop over each of the seven letters in the string 'letters' and counting how many times that letter appears.
word = 'letters'
letter_counts = {letter: word.count(letter) for letter in set(word)}
letter_counts
  • How many times do we count 't' here?

Dictionary Comprehensions

  • Dictionary comprehensions can also have if tests and multiple for clauses:

vowels = 'aeiou'
word = 'onomatopoeia'
vowel_counts = {letter: word.count(letter) for letter in set(word)
if letter in vowels}
vowel_counts
12 / 39

Sets

  • A set is like a dictionary with its values thrown away, leaving only the keys.

    • As with a dictionary, each key must be unique.
  • We use a set when we only want to know that something exists, and nothing else about it.

    • Use a dictionary if we want to attach some information to the key as a value.
13 / 39

Sets

Common things to do with sets

  • The null or empty set is a set with zero elements.
14 / 39

Sets

Create with set()

  • To create a set, we use the set() function or enclose one or more comma-separated values in curly brackets:
empty_set = set()
empty_set
even_numbers = {0, 2, 4, 6, 8}
even_numbers
odd_numbers = {1, 3, 5, 7, 9}
odd_numbers

Convert with set()

  • We can create a set from a list, string, tuple, or dictionary, discarding any duplicate values.
set( 'letters' )
set( ['Dasher', 'Dancer', 'Prancer', 'Mason-Dixon'] )
set( ('Ummagumma', 'Echoes', 'Atom Heart Mother') )
set( {'apple': 'red', 'orange': 'orange', 'cherry': 'red'} )
  • Sets are unordered.

Get Length with len()

  • Let's count our reindeer:
reindeer = set( ['Dasher', 'Dancer', 'Prancer', 'Mason-Dixon'] )
len(reindeer)

Add an Item with add()

  • Throw another item into a set with the set add() method
s = set((1,2,3))
s
s.add(4)
s

Delete an Item with remove()

  • We can delete a value from a set by value:
s = set((1,2,3))
s.remove(3)
s

Iterate with for and in

  • We can iterate over all items in a set:
furniture = set(('sofa', 'ottoman', 'table'))
for piece in furniture:
print(piece)
15 / 39

Sets

Test for a Value with in

  • Here is a dictionary called drinks.
    • Each key is the name of a mixed drink, and the corresponding value is a set of that drink's ingredients:
    • A set is just a bunch of values, and a dictionary contains key : value pairs.
drinks = { 'martini': {'vodka', 'vermouth'},
'black russian': {'vodka', 'kahlua'},
'white russian': {'cream', 'kahlua', 'vodka'},
'manhattan': {'rye', 'vermouth', 'bitters'},
'screwdriver': {'orange juice', 'vodka'} }
  • Print drinks that contain vodka:
for name, contents in drinks.items():
if 'vodka' in contents:
print(name)
  • Print drinks that neither contain either cream nor vermouth but do vodka:
for name, contents in drinks.items():
if 'vodka' in contents \
and not ('vermouth' in contents or 'cream' in contents):
print(name)
16 / 39

Sets

Combinations and Operators

  • Here are some examples to consider for set combinations and operations.
drinks = { 'martini': {'vodka', 'vermouth'},
'black russian': {'vodka', 'kahlua'},
'white russian': {'cream', 'kahlua', 'vodka'} }
bruss = drinks['black russian']
wruss = drinks['white russian']
a = {1, 2}
b = {2, 3}
  • We get the intersection (members common to both sets) with the special punctuation symbol &.
    • The set intersection() function does the same.
a & b
a.intersection(b)
bruss & wruss
  • Let's get the union (members of either set) by using | or the set union() function:
a | b
a.union(b)
bruss | wruss
  • The difference (members of the first set but not the second) is obtained by using the character - or the difference() function:
a - b
a.difference(b)
bruss - wruss
wruss - bruss
  • The exclusive or (items in one set or the other, but not both) uses ^ or symmetric_difference():
a ^ b
a.symmetric_difference(b)
bruss ^ wruss
  • We can check whether one set is a subset of another (all members of the first set are also in the second set) by using <= or issubset():
a <= b
a.issubset(b)
bruss <= wruss
a <= a # any set is a subset of itself?
a.issubset(a)
  • To be a proper subset, the second set needs to have all the members of the first and more.
    • Calculate it by using <:
a < b
b < a
bruss < wruss
  • A superset is the opposite of a subset (all members of the second set are also members of the first). This uses >= or issuperset():
a >= b
a.issuperset(b)
wruss >= bruss
a >= a # any set is a superset of itself?
a.issuperset(a)
  • To be a proper superset, the first set needs to have all the members of the second and more.
    • Calculate it by using >:
a > b
wruss > bruss
a > a
  • What if we want to check for combinations of set values?
    • Suppose that we want to find any drink that has orange juice or vermouth.
    • Let's use the set intersection operator, which is an ampersand (&):
for name, contents in drinks.items():
if contents & {'vermouth', 'orange juice'}:
print(name)
  • Let's rewrite the example from the previous section, in which we wanted vodka but neither cream nor vermouth:
for name, contents in drinks.items():
if 'vodka' in contents and not contents & {'vermouth', 'cream'}:
print(name)
17 / 39

Sets

Set Comprehensions

  • Sets also have comprehensions:

a_set = {number for number in range(1,6) if number % 3 == 1}

Create an Immutable Set with frozenset()

  • If we want to create a set that can't be changed, call the frozenset() function with any iterable argument:
frozenset([3, 2, 1])
frozenset(set([2, 1, 3]))
frozenset({3, 1, 2})
frozenset( (2, 3, 1) )
fs = frozenset([3, 2, 1])
fs
fs.add(4)
18 / 39

Data Structures So Far

  • To review, we make:
    • A list by using square brackets ([])
    • A tuple by using commas and optional parentheses (())
    • A dictionary or set by using curly brackets ({})
marx_list = ['Groucho', 'Chico', 'Harpo']
marx_tuple = ('Groucho', 'Chico', 'Harpo')
marx_dict = {'Groucho': 'banjo', 'Chico': 'piano', 'Harpo': 'harp'}
marx_set = {'Groucho', 'Chico', 'Harpo'}
  • For all but sets, we access a single element with square brackets.
    • For the list and the tuple, the value between the square brackets is an integer offset.
    • For the dictionary, we access a single element with a key.
marx_list[2]
marx_tuple[2]
marx_dict['Harpo']
'Harpo' in marx_set
  • For the list, the tuple, and the dictionary, the result is a value.
  • For the set, the result is either there or it's not; there's no index or key.
19 / 39

Make Bigger Data Structures

  • We worked up from simple booleans, numbers, and strings to lists, tuples, sets, and dictionaries.
  • We can combine these built-in data structures into bigger, more complex structures of our own.

  • Let's start with three different lists:

newyork = ['Geneseo', 'Rochester', 'Buffalo']
california = ['San Francisco', 'Los Angeles', 'San Diego']
texas = ['Dallas', 'Houston', 'Austin']
  • We can make a tuple that contains each list as an element:
tuple_of_lists = newyork, california, texas
tuple_of_lists
  • We can make a list that contains the three lists:
list_of_lists = [newyork, california, texas]
list_of_lists
  • Finally, let's create a dictionary of lists.
    • In this example, let's use the abbreviated name of the state as the key and the list of cities as the value:
dict_of_lists = {'NY': newyork, 'CA': california, 'TX': texas}
dict_of_lists
20 / 39

Dictionaries and Sets

Class Exercises

1. Make an English-to-French dictionary called e2f and print it. Here are your starter words: dog is chien, cat is chat, and walrus is morse.

2. Using your three-word dictionary e2f, print the French word for walrus.

3. Make a French-to-English dictionary called f2e from e2f Use the items method.

4. Print the English equivalent of the French word chien.

5. Print the set of English words from e2f.

21 / 39

Dictionaries and Sets

Class Exercises

6. Make a multilevel dictionary called life. Use these strings for the topmost keys: 'animals', 'plants', and 'other'. Make the 'animals' key refer to another dictionary with the keys 'cats', 'octopi', and 'emus'. Make the 'cats' key refer to a list of strings with the values 'Henri', 'Grumpy', and 'Lucy'. Make all the other keys refer to empty dictionaries.

7. Print the top-level keys of life.

8. Print the keys for life['animals'].

9. Print the values for life['animals']['cats'].

22 / 39

Dictionaries and Sets

Class Exercises

10. Use a dictionary comprehension to create the dictionary squares. Use range(10) to return the keys, and use the square of each key as its value.

11. Use a set comprehension to create the set odd from the odd numbers in range(10).

23 / 39

Functions


24 / 39

Functions

  • So far, all of our Python code examples have been little fragments.
    • These are good for small tasks, but no one wants to retype fragments all the time.
    • We need some way of organizing larger code into manageable pieces.
  • The first step to code reuse is the function: a named piece of code, separate from all others.
  • A function can take any number and type of input parameters and return any number and type of output results.
  • We can do two things with a function:
    • Define it, with zero or more parameters
    • Call it, and get zero or more results
25 / 39

Functions

Define a Function with def

  • To define a Python function, we type def, the function name, parentheses enclosing any input parameters to the function, and then finally, a colon (:).

  • Function names have the same rules as variable names (they must start with a letter or and contain only letters, numbers, or ).

  • Let's define a very simple function that has no parameters.
def do_nothing():
pass # indention is needed here
  • We use the pass statement when we want Python to do nothing.
    • It's the equivalent of This page intentionally left blank.
  • We call the do_nothing() function just by typing its name and parentheses.
do_nothing()
26 / 39

Functions

Call a Function with Parentheses

  • Let's define and call another function that has no parameters but prints a single word:
def make_a_sound():
print('quack')
make_a_sound()
  • When we called this function, Python ran the code inside its definition.
    • In this case, it printed a single word and returned to the main program.
  • Let's try a function that has no parameters but returns a value:
def agree():
return True
  • We can call the agree() function and test its returned value by using if:
if agree():
print('Splendid!')
else:
print('That was unexpected.')
27 / 39

Functions

Arguments and Parameters

  • Let's define the function echo() with one parameter called anything.
    • It uses the return statement to send the value of anything back to its caller twice, with a space between:
def echo(anything):
return anything + ' ' + anything
echo('Geneseo')
  • The values we pass into the function when we call it are known as arguments.

  • When we call a function with arguments, the values of those arguments are copied to their corresponding parameters inside the function.

28 / 39

Functions

Arguments and Parameters

def echo(anything):
return anything + ' ' + anything
echo('Geneseo')
  • The function echo() was called with the argument string 'Geneseo'.

    • The value 'Geneseo' was copied within echo() to the parameter anything, and then returned (in this case doubled, with a space) to the caller.
29 / 39

Functions

Arguments and Parameters

  • Let's write a function that takes an input argument and actually does something with it.
    • Call it commentary, have it take an input string parameter called color, and make it return the string description to its caller:
def commentary(color):
if color == 'red':
return "It's a tomato."
elif color == "green":
return "It's a green pepper."
elif color == 'bee purple':
return "I don't know what it is, but only bees can see it."
else:
return "I've never heard of the color " + color + "."
30 / 39

Functions

Arguments and Parameters

  • Call the function commentary() with the string argument 'blue'.
comment = commentary('blue')
  • The function does the following:
    • Assigns the value 'blue' to the function's internal color parameter
    • Runs through the if-elif-else logic chain
    • Returns a string
  • The caller then assigns the string to the variable comment.
  • What did we get back?
print(comment)
  • A function can take any number of input arguments (including zero) of any type.

  • It can return any number of output results (also including zero) of any type.

  • If a function doesn't call return explicitly, the caller gets the result None.
def do_nothing():
pass
print(do_nothing())
31 / 39

Functions

None Is Useful

  • None is a special Python value that holds a place when there is nothing to say.

    • It is not the same as the boolean value False, although it looks false when evaluated as a boolean.
thing = None
if thing:
print("It's some thing")
else:
print("It's no thing")
  • To distinguish None from a boolean False value, use Python's is operator:
thing = None
if thing is None:
print("It's some thing")
else:
print("It's no thing")
  • We'll need None to distinguish a missing value from an empty value.
  • Zero-valued numbers, empty strings (''), lists ([]), tuples ((,)), dictionaries ({}), and sets (set()) are all False, but are not the same as None.
  • Let's write a quick function that prints whether its argument is None, True, or False:
def whatis(thing):
if thing is None:
print(thing, "is None")
elif thing:
print(thing, "is True")
else:
print(thing, "is False")
  • Let's run some sanity tests:
whatis(None)
whatis(True)
whatis(False)
  • How about some real values?
whatis(0)
whatis(0.0)
whatis('')
whatis("")
whatis('''''')
whatis(())
whatis([])
whatis({})
whatis(set())
  • How about some real values?
whatis(0.00001)
whatis([0])
whatis([''])
whatis(' ')
32 / 39

Functions

Positional Arguments

  • The most familiar types of arguments are positional arguments, whose values are copied to their corresponding parameters in order.

  • This function builds a dictionary from its positional input arguments and returns it:

def menu(wine, entree, dessert):
return {'wine': wine, 'entree': entree, 'dessert': dessert}
menu('chardonnay', 'chicken', 'cake')

Positional Arguments

  • A downside of positional arguments is that we need to remember the meaning of each position.
menu('beef', 'bagel', 'bordeaux')

Keyword Arguments

  • To avoid positional argument confusion, we can specify arguments by the names of their corresponding parameters, even in a different order from their definition in the function:
menu(entree='beef', dessert='bagel', wine='bordeaux')
# Specify the wine first, but use keyword arguments for the entree and dessert:
menu('frontenac', dessert='flan', entree='fish')
  • If we call a function with both positional and keyword arguments, the positional arguments need to come first.
33 / 39

Functions

Specify Default Parameter Values

  • We can specify default values for parameters.
    • The default is used if the caller does not provide a corresponding argument.
    • Try calling menu() without the dessert argument:
def menu(wine, entree, dessert='pudding'):
return {'wine': wine, 'entree': entree, 'dessert': dessert}
menu('chardonnay', 'chicken')
  • We can specify default values for parameters.
    • If we provide an argument, it's used instead of the default:
def menu(wine, entree, dessert='pudding'):
return {'wine': wine, 'entree': entree, 'dessert': dessert}
menu('dunkelfelder', 'duck', 'doughnut')
34 / 39

Functions

Specify Default Parameter Values

  • The buggy() function is expected to run each time with a fresh empty result list, add the arg argument to it, and then print a single-item list.
def buggy(arg, result=[]):
result.append(arg)
print(result)
buggy('a')
buggy('b') # expect ['b']
  • There's a bug: it's empty only the first time it's called.
    • The second time, result still has one item from the previous call.
  • It would have worked if it had been written like this:
def works(arg):
result = []
result.append(arg)
return result
works('a')
works('b')
  • The fix is to pass in something else to indicate the first call:
def nonbuggy(arg, result=None):
if result is None:
result = []
result.append(arg)
print(result)
nonbuggy('a')
nonbuggy('b')
35 / 39

Functions

Explode/Gather Positional Arguments with *

  • When an asterisk (*) is used inside the function with a parameter, it groups a variable number of positional arguments into a single tuple of parameter values.
def print_args(*args):
print('Positional tuple:', args)
print_args()
print_args(3, 2, 1, 'wait!', 'uh...')
  • If our function has required positional arguments, as well, put them first; *args goes at the end and grabs all the rest:
def print_more(required1, required2, *args):
print('Need this one:', required1)
print('Need this one too:', required2)
print('All the rest:', args)
print_more('cap', 'gloves', 'scarf', 'monocle', 'mustache wax')
  • We can pass positional argument to a function, which will match them inside to positional parameters.

  • We can pass a tuple argument to a function, and inside it will be a tuple parameter.

  • We can pass positional arguments to a function, and gather them inside as the parameter *args, which resolves to the tuple args.

  • We can also "explode" a tuple argument called args to positional parameters *args inside the function, which will be regathered inside into the tuple parameter args:
def print_args(*args):
print('Positional tuple:', args)
print_args(2, 5, 7, 'x')
args = (2,5,7,'x')
print_args(args)
print_args(*args)
  • We can only use the * syntax in a function call or definition:
args
  • Outside the function, *args explodes the tuple args into comma-separated positional parameters.

  • Inside the function, *args gathers all of the positional arguments into a single args tuple.

36 / 39

Functions

Explode/Gather Positional Arguments with **

  • We can use two asterisks (**) to group keyword arguments into a dictionary, where the argument names are the keys, and their values are the corresponding dictionary values.
def print_kwargs(**kwargs):
print('Keyword arguments:', kwargs)
print_kwargs()
print_kwargs(wine='merlot', entree='mutton', dessert='macaroon')
  • Inside the function, kwargs is a dictionary parameter.
  • We can pass keyword arguments to a function, which will match them inside to keyword parameters.

  • We can pass a dictionary argument to a function, and inside it will be dictionary parameters.

  • We can pass one or more keyword arguments (name=value) to a function, and gather them inside as **kwargs, which resolves to the dictionary parameter called kwargs.

  • Outside a function, **kwargs explodes a dictionary kwargs into name=value arguments.

  • Inside a function, **kwargs gathers name=value arguments into the single dictionary parameter kwargs.

37 / 39

Functions

Keyword-Only Arguments

  • a keyword-only argument is an argument that can only be provided as a keyword argument when a function is called.
    • It is recommended to be provided as name=value.
def print_data(data, *, start=0, end=100):
for value in (data[start:end]):
print(value)
  • The single * in the definition above means that the parameters start and end must be provided as named arguments if we don’t want their default values.
data = ['a', 'b', 'c', 'd', 'e', 'f']
print_data(data)
print_data(data, start=4)
print_data(data, end=2)
def print_data2(data, *, start, end):
for value in (data[start:end]):
print(value)
print_data2(data)
print_data2(data, start=4)
print_data2(data, end=2)
print_data2(data, start = 2, end = 4)
  • start and end are required arguments, because they doesn't have a default value and they must be specified as a keyword argument when we call the print_data2() function.
38 / 39

Functions

Mutable and Immutable Arguments

  • Remember that if you assigned the same list to two variables, you could change it by using either one? And that you could not if the variables both referred to something like an integer or a string?

  • If an argument is mutable, its value can be changed from inside the function via its corresponding parameter.

outside = ['one', 'fine', 'day']
def mangle(arg):
arg[1] = 'terrible!'
outside
mangle(outside)
outside
39 / 39

Dictionaries and Sets


2 / 39
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
oTile View: Overview of Slides
Esc Back to slideshow