Crash course on scope in functions
Not all objects are accessible everywhere in a script.
Scope – part ofthe program where an object or name may be accessible
- Global scope – defined in the main body of a script
- Local scope – defined inside a function
- Built-in scope – names in the pre-defined built-ins module
In the example below new_val is defined only in the scope of the function and cannot be accessed outside of it
def square(value):
"""Returns the square of a number."""
new_val = value ** 2
return new_val
square(3)In the example below it is defined globally and can be accessed. BUT in the function it is not changing the value of the new_val variable so if we ran the code below, the function will return 100 but the value of new_val will still be 10.
new_val = 10
def square(value):
"""Returns the square of a number."""
new_val = value ** 2
return new_val
square(3)If we want to change the value of new_val in the function then we have to do :
new_val = 10
def square(value):
"""Returns the square of a number."""
global new_val
new_val = new_val ** 2
return new_val
square(3)We added a global definition of new_val in the function.
Nested functions
Nested functions are functions in functions :
def outer( ... ):
""" ... """
x = ...
def inner( ... ):
""" ... """
y = x ** 2
return ...Instead of doing this :
def mod2plus5(x1, x2, x3):
"""Returns the remainder plus 5 of three values."""
new_x1 = x1 % 2 + 5
new_x2 = x2 % 2 + 5
new_x3 = x3 % 2 + 5
return (new_x1, new_x2, new_x3)We can do this :
def mod2plus5(x1, x2, x3):
"""Returns the remainder plus 5 of three values."""
def inner(x):
"""Returns the remainder plus 5 of a value."""
return x % 2 + 5
return (inner(x1), inner(x2), inner(x3))
print(mod2plus5(1,2,3))
->(6,5,6)You can also return functions ! This is tricky so pay attention, in the return statement of the first function you will return the inner function :
def raise_val(n):
"""Return the inner function."""
def inner(x):
"""Raise x to the power of n."""
raised = x ** n
return raised
return inner
square = raise_val(2)
cube = raise_val(3)
print(square(2), cube(4))
->4,64Using Nonlocal :
def outer():
"""Prints the value of n."""
n = 1
def inner():
nonlocal n
n = 2
print(n)
inner()
print(n)
outer()
->2
->2From the exercise :
# Define echo_shout()
def echo_shout(word):
"""Change the value of a nonlocal variable"""
# Concatenate word with itself: echo_word
echo_word=word+word
# Print echo_word
print(echo_word)
# Define inner function shout()
def shout():
"""Alter a variable in the enclosing scope"""
# Use echo_word in nonlocal scope
nonlocal echo_word
# Change echo_word to echo_word concatenated with '!!!'
echo_word = echo_word+'!!!'
# Call function shout()
shout()
# Print echo_word
print(echo_word)
# Call function echo_shout() with argument 'hello'
echo_shout('hello') Default and exible arguments
How to add default arguments :
def power(number, pow=1):
"""Raise number to the power of pow."""
new_value = number ** pow
return new_value
power(9, 2)
->81
power(9,1)
->9
power(9)
->9if you put = something for a variable in the def, you assign a by default value to it, so even if you don’t pass it in the call the function will take the by default value.
Now for flexible args, you can pass *args in the definition of the function if you want to accept any number of variables passed :
def add_all(*args):
"""Sum all values in *args together."""
# Initialize sum
sum_all = 0
# Accumulate the sum
for num in args:
sum_all += num
return sum_all
add_all(1)
->1
add_all(5,10,15,20)
->50You can also use **kwargs :
**kwargs is a dictionary of keyword arguments. The ** allows us to pass any number of keyword arguments. A keyword argument is basically a dictionary.
def print_all(**kwargs):
"""Print out key-value pairs in **kwargs."""
# Print out the key-value pairs
for key, value in kwargs.items():
print(key + \": \" + value)
print_all(name="dumbledore", job="headmaster")
->
job: headmaster
name: dumbledore
From the exercises, take notice at the hodgepodge += word that concatenates in a loop new words in a string.
# Define gibberish
def gibberish(*args):
"""Concatenate strings in *args together."""
# Initialize an empty string: hodgepodge
hodgepodge=''
# Concatenate the strings in args
for word in args:
hodgepodge += word
# Return hodgepodge
return(hodgepodge)
# Call gibberish() with one string: one_word
one_word = gibberish('luke')
# Call gibberish() with five strings: many_words
many_words = gibberish("luke", "leia", "han", "obi", "darth")
# Print one_word and many_words
print(one_word)
print(many_words)
->
luke
lukeleiahanobidarthAnd another one with passing lines in the print 🙂
# Define report_status
def report_status(**kwargs):
"""Print out the status of a movie character."""
print("\nBEGIN: REPORT\n")
# Iterate over the key-value pairs of kwargs
for key, value in kwargs.items():
# Print out the keys and values, separated by a colon ':'
print(key + ": " + value)
print("\nEND REPORT")
# First call to report_status()
report_status(name='luke', affiliation='jedi', status='missing')
# Second call to report_status()
report_status(name='anakin', affiliation='sith lord', status='deceased')
->
BEGIN: REPORT
name: luke
affiliation: jedi
status: missing
END REPORT
BEGIN: REPORT
name: anakin
affiliation: sith lord
status: deceased
BEGIN: REPORT And finally, we can see how it looks with the tweeter counter thing, we will try to pass as many columns as the user wants :
# Define count_entries()
def count_entries(df, *args):
"""Return a dictionary with counts of
occurrences as value for each key."""
#Initialize an empty dictionary: cols_count
cols_count = {}
# Iterate over column names in args
for col_name in args:
# Extract column from DataFrame: col
col = df[col_name]
# Iterate over the column in DataFrame
for entry in col:
# If entry is in cols_count, add 1
if entry in cols_count.keys():
cols_count[entry] += 1
# Else add the entry to cols_count, set the value to 1
else:
cols_count[entry] = 1
# Return the cols_count dictionary
return cols_count
# Call count_entries(): result1
result1 = count_entries(tweets_df,'lang')
# Call count_entries(): result2
result2 = count_entries(tweets_df, 'lang', 'source')
# Print result1 and result2
print(result1)
print(result2)