Functions¶
In this lecture you’ll learn to write functions, which are named blocks of code that are designed to do one specific job. When you want to perform a particular task that you’ve defined in a function, you call the function responsible for it. If you need to perform that task multiple times throughout your program, you don’t need to type all the code for the same task again and again; you just call the function dedicated to handling that task, and the call tells Python to run the code inside the function. You’ll find that using functions makes your programs easier to write, read, test, and fix.
In this lecture you’ll also learn ways to pass information to functions. You’ll learn how to write certain functions whose primary job is to display information and other functions designed to process data and return a value or set of values. Finally, you’ll learn to store functions in separate files called modules to help organize your main program files.
DEFINING A FUNCTION ¶
Here’s a simple function named greet_user() that prints a greeting:
➊ def greet_user():
➋ """Display a simple greeting."""
➌ print("Hello!")
➍ greet_user()
This example shows the simplest structure of a function. The line at ➊ uses the keyword def to inform Python that you’re defining a function. This is the function definition, which tells Python the name of the function and, if applicable, what kind of information the function needs to do its job. The parentheses hold that information. In this case, the name of the function is greet_user(), and it needs no information to do its job, so its parentheses are empty. (Even so, the parentheses are required.) Finally, the definition ends in a colon.
Any indented lines that follow def greet_user(): make up the body of the function. The text at ➋ is a comment called a docstring, which describes what the function does. Docstrings are enclosed in triple quotes, which Python looks for when it generates documentation for the functions in your programs.
The line print("Hello!") ➌ is the only line of actual code in the body of this function, so greet_user() has just one job: print("Hello!").
When you want to use this function, you call it. A function call tells Python to execute the code in the function. To call a function, you write the name of the function, followed by any necessary information in parentheses, as shown at ➍. Because no information is needed here, calling our function is as simple as entering greet_user(). As expected, it prints Hello!:
def greet_user():
"""Display a simple greeting."""
print("Hello!")
greet_user()
Hello!
Passing Information to a Function¶
Modified slightly, the function greet_user() can not only tell the user Hello! but also greet them by name. For the function to do this, you enter username in the parentheses of the function’s definition at def greet_user(). By adding username here you allow the function to accept any value of username you specify. The function now expects you to provide a value for username each time you call it. When you call greet_user(), you can pass it a name, such as 'jesse', inside the parentheses:
def greet_user(username): #parameter, name doesn't matter
"""Display a simple greeting."""
print(f"Hello, {username.title()}!")
greet_user('jesse')
Hello, Jesse!
PASSING ARGUMENTS ¶
Because a function definition can have multiple parameters, a function call may need multiple arguments. You can pass arguments to your functions in a number of ways. You can use positional arguments, which need to be in the same order the parameters were written; keyword arguments, where each argument consists of a variable name and a value; and lists and dictionaries of values. Let’s look at each of these in turn.
Positional Arguments¶
When you call a function, Python must match each argument in the function call with a parameter in the function definition. The simplest way to do this is based on the order of the arguments provided. Values matched up this way are called positional arguments.
To see how this works, consider a function that displays information about pets. The function tells us what kind of animal each pet is and the pet’s name, as shown here:
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamster', 'harry')
#number of parameter must be same, sequense also be same
I have a hamster. My hamster's name is Harry.
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamstesssr', 'harddry')
I have a hamstesssr. My hamstesssr's name is Harddry.
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')
I have a hamster. My hamster's name is Harry. I have a dog. My dog's name is Willie.
Order Matters in Positional Arguments¶
You can get unexpected results if you mix up the order of the arguments in a function call when using positional arguments:
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet('harry', 'hamster')
I have a harry. My harry's name is Hamster.
Keyword Arguments¶
A keyword argument is a name-value pair that you pass to a function. You directly associate the name and the value within the argument, so when you pass the argument to the function, there’s no confusion (you won’t end up with a harry named Hamster). Keyword arguments free you from having to worry about correctly ordering your arguments in the function call, and they clarify the role of each value in the function call.
Let’s rewrite pets.py using keyword arguments to call describe_pet():
def describe_pet(animal_type, pet_name):
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet(animal_type='hamster', pet_name='harry')
I have a hamster. My hamster's name is Harry.
describe_pet(animal_type='hamster', pet_name='harry')
describe_pet(pet_name='harry', animal_type='hamster')
I have a hamster. My hamster's name is Harry. I have a hamster. My hamster's name is Harry.
Default Values¶
When writing a function, you can define a default value for each parameter. If an argument for a parameter is provided in the function call, Python uses the argument value. If not, it uses the parameter’s default value. So when you define a default value for a parameter, you can exclude the corresponding argument you’d usually write in the function call. Using default values can simplify your function calls and clarify the ways in which your functions are typically used.
For example, if you notice that most of the calls to describe_pet() are being used to describe dogs, you can set the default value of animal_type to 'dog'. Now anyone calling describe_pet() for a dog can omit that information:
def describe_pet(pet_name, animal_type='dog'):# default value 'dog'
"""Display information about a pet."""
print(f"\nI have a {animal_type}.")
print(f"My {animal_type}'s name is {pet_name.title()}.")
describe_pet(pet_name='willie')
I have a dog. My dog's name is Willie.
def info(name, dept = 'geography'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
info('Zhanchao')
My name is Zhanchao. I came from Geography department.
def info(name, dept = 'geography'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
info('Zhanchao', 'environmental studies')
My name is Zhanchao. I came from Environmental Studies department.
def info(name, dept = 'geography', state = 'NY'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
print(f'I am living in {state} state.')
info('Zhanchao')
My name is Zhanchao. I came from Geography department. I am living in NY state.
def info(name, dept = 'geography', state = 'NY'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
print(f'I am living in {state} state.')
info('Zhanchao', state = 'PA')
# name is only useful, if you want to provide something not in regular sequence
My name is Zhanchao. I came from Geography department. I am living in PA state.
# doesn't work, if it does not provide specific argument. It will treat
# with order
def info(name, dept = 'geography', state = 'NY'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
print(f'I am living in {state} state.')
info('Zhanchao', 'PA')
# see the different between this code and previous one
My name is Zhanchao. I came from Pa department. I am living in NY state.
def info(name, dept = 'geography', state = 'NY', major):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
print(f'I am living in {state} state.')
print(f'My major is {major.title()}.')
info('Zhanchao', 'geography')
Cell In[18], line 1 def info(name, dept = 'geography', state = 'NY', major): ^ SyntaxError: non-default argument follows default argument
# requirement must come first and optional come second
def info(name, major, dept = 'geography', state = 'NY'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
print(f'I am living in {state} state.')
print(f'My major is {major.title()}.')
info('Zhanchao', 'geography')
My name is Zhanchao. I came from Geography department. I am living in NY state. My major is Geography.
def info(name, major, dept = 'geography', state = 'NY'):
print(f'My name is {name.title()}.')
print(f'I came from {dept.title()} department.')
print(f'I am living in {state} state.')
print(f'My major is {major.title()}.')
info('Zhanchao', 'geography', state = 'CA')
My name is Zhanchao. I came from Geography department. I am living in CA state. My major is Geography.
Equivalent Function Calls¶
Because positional arguments, keyword arguments, and default values can all be used together, often you’ll have several equivalent ways to call a function. Consider the following definition for describe_pet() with one default value provided:
def describe_pet(pet_name, animal_type='dog'):
With this definition, an argument always needs to be provided for pet_name, and this value can be provided using the positional or keyword format. If the animal being described is not a dog, an argument for animal_type must be included in the call, and this argument can also be specified using the positional or keyword format.
All of the following calls would work for this function:
# A dog named Willie.
describe_pet('willie')
describe_pet(pet_name='willie')
# A hamster named Harry.
describe_pet('harry', 'hamster')
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')
I have a dog. My dog's name is Willie. I have a dog. My dog's name is Willie. I have a hamster. My hamster's name is Harry. I have a hamster. My hamster's name is Harry. I have a hamster. My hamster's name is Harry.
RETURN VALUES ¶
A function doesn’t always have to display its output directly. Instead, it can process some data and then return a value or set of values. The value the function returns is called a return value. The return statement takes a value from inside a function and sends it back to the line that called the function. Return values allow you to move much of your program’s grunt work into functions, which can simplify the body of your program.
Returning a Simple Value¶
Let’s look at a function that takes a first and last name, and returns a neatly formatted full name:
def get_formatted_name(first_name, last_name):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {last_name}"
return full_name.title()
# Return must be the last line of code in the function.
# Any codes after return will not be executed.
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
Jimi Hendrix
def get_formatted_name(first_name, last_name):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {last_name}"
# if there is no return within the function. There will be nothing left
# and cannot be assigned into a variable
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
None
# variable defined within the function, is only alive in the function
'''
def get_formatted_name(first_name, last_name)
'''
# after that, there will be no value within the varible
first_name
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[27], line 6 2 ''' 3 def get_formatted_name(first_name, last_name) 4 ''' 5 # after that, there will be no value within the varible ----> 6 first_name NameError: name 'first_name' is not defined
# even if the default value, all the value is within the function
#the data destory after you run the function
def get_formatted_name(first_name, last_name = 'brown'):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {last_name}"
return full_name.title()
musician = get_formatted_name('jimi')
print(musician)
last_name
Jimi Brown
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[29], line 8 6 musician = get_formatted_name('jimi') 7 print(musician) ----> 8 last_name NameError: name 'last_name' is not defined
function error¶
Function may have error. The fact is when you try to define a function. Only the code
def human(a,b)
have been check by python. All the other information haven't be checked, it will only be checked after the function is called out example
def get_formatted_name(first_name, last_name = 'brown'):
a=b
full_name = f"{first_name} {last_name}"
return full_name.title()
# no error found, even a and b are not defined
#after called out, error appear
get_formatted_name('Emily')
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[31], line 2 1 #after called out, error appear ----> 2 get_formatted_name('Emily') Cell In[30], line 3, in get_formatted_name(first_name, last_name) 1 def get_formatted_name(first_name, last_name = 'brown'): ----> 3 a=b 4 full_name = f"{first_name} {last_name}" 5 return full_name.title() NameError: name 'b' is not defined
Making an Argument Optional¶
Sometimes it makes sense to make an argument optional so that people using the function can choose to provide extra information only if they want to. You can use default values to make an argument optional.
def get_formatted_name(first_name, last_name, middle_name=''):
"""Return a full name, neatly formatted."""
if middle_name:
full_name = f"{first_name} {middle_name} {last_name}"
else:
full_name = f"{first_name} {last_name}"
return full_name.title()
musician = get_formatted_name('jimi', 'hendrix')
print(musician)
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)
Jimi Hendrix John Lee Hooker
Returning a Dictionary¶
A function can return any kind of value you need it to, including more complicated data structures like lists and dictionaries. For example, the following function takes in parts of a name and returns a dictionary representing a person:
def build_person(first_name, last_name):
"""Return a dictionary of information about a person."""
person = {'first': first_name, 'last': last_name}
return person
musician = build_person('jimi', 'hendrix')
print(musician)
{'first': 'jimi', 'last': 'hendrix'}
Using a Function with a while Loop¶
You can use functions with all the Python structures you’ve learned about so far. For example, let’s use the get_formatted_name() function with a while loop to greet users more formally. Here’s a first attempt at greeting people using their first and last names:
def get_formatted_name(first_name, last_name):
"""Return a full name, neatly formatted."""
full_name = f"{first_name} {last_name}"
return full_name.title()
# This is an infinite loop!
while True:
print("\nPlease tell me your name:")
print("(enter 'q' at any time to quit)")
f_name = input("First name: ")
if f_name == 'q':
break
l_name = input("Last name: ")
if l_name == 'q':
break
formatted_name = get_formatted_name(f_name, l_name)
print(f"\nHello, {formatted_name}!")
Please tell me your name: (enter 'q' at any time to quit) First name: zhanchao Last name: yang Hello, Zhanchao Yang! Please tell me your name: (enter 'q' at any time to quit) First name: q
PASSING A LIST ¶
You’ll often find it useful to pass a list to a function, whether it’s a list of names, numbers, or more complex objects, such as dictionaries. When you pass a list to a function, the function gets direct access to the contents of the list. Let’s use functions to make working with lists more efficient.
Say we have a list of users and want to print a greeting to each. The following example sends a list of names to a function called greet_users(), which greets each person in the list individually:
def greet_users(names):
"""Print a simple greeting to each user in the list."""
for name in names:
msg = f"Hello, {name.title()}!"
print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
Hello, Hannah! Hello, Ty! Hello, Margot!
def select_student(names):
result = []
for name in names:
if len(name) >= 6:
result.append(name)
return result
student= ['eric', 'mathew erin', 'chenhua']
select_student(student)
['mathew erin', 'chenhua']
select_student(['kkkkkk', 'shjidjdijn', 'hgdsiua'])
['kkkkkk', 'shjidjdijn', 'hgdsiua']
Using Arbitrary Keyword Arguments¶
Sometimes you’ll want to accept an arbitrary number of arguments, but you won’t know ahead of time what kind of information will be passed to the function. In this case, you can write functions that accept as many key-value pairs as the calling statement provides. One example involves building user profiles: you know you’ll get information about a user, but you’re not sure what kind of information you’ll receive. The function build_profile() in the following example always takes in a first and last name, but it accepts an arbitrary number of keyword arguments as well:
def build_profile(first, last, **user_info): # '** means a dictionary, that you can put as many argument as you want
"""Build a dictionary containing everything we know about a user."""
user_info['first_name'] = first
user_info['last_name'] = last
return user_info #return a dictionary
user_profile = build_profile('albert', 'einstein',
location='princeton',
field='physics')
print(user_profile)
{'location': 'princeton', 'field': 'physics', 'first_name': 'albert', 'last_name': 'einstein'}
def build_profile(first, last, **user_info):# more flexibale
"""Build a dictionary containing everything we know about a user."""
user_info['first_name'] = first
user_info['last_name'] = last
return user_info
user_profile = build_profile('albert', 'einstein',
location='princeton',
field='physics',
department='geography',
major= 'gis')
print(user_profile)
{'location': 'princeton', 'field': 'physics', 'department': 'geography', 'major': 'gis', 'first_name': 'albert', 'last_name': 'einstein'}
def build_profile(first, last, dept ='geography', **kwargs):# more flexibale
"""Build a dictionary containing everything we know about a user."""
kwargs['first_name'] = first
kwargs['last_name'] = last
return kwargs
user_profile = build_profile('albert', 'einstein',
department='geography',
location='princeton',
field='physics',
major= 'gis')
print(user_profile)
{'department': 'geography', 'location': 'princeton', 'field': 'physics', 'major': 'gis', 'first_name': 'albert', 'last_name': 'einstein'}
def build_profile(first, last, dept ='geography', **kwargs):# more flexibale
"""Build a dictionary containing everything we know about a user."""
print(kwargs)
kwargs['first_name'] = first
kwargs['last_name'] = last
return kwargs
user_profile = build_profile('albert', 'einstein',
department='geography',
location='princeton',
field='physics',
major= 'gis')
print(user_profile)
{'department': 'geography', 'location': 'princeton', 'field': 'physics', 'major': 'gis'} {'department': 'geography', 'location': 'princeton', 'field': 'physics', 'major': 'gis', 'first_name': 'albert', 'last_name': 'einstein'}
Finish¶
References¶
- Matthes, Eric (2022). Python Crash Course, 3rd Edition: A Hands-On, Project-Based Introduction to Programming. No Starch Press. ISBN: 978-1593279288. (Publisher website)
- Dr.Qiusheng Wu online lecture