This article is participating in Python Theme Month. See the link for details

Functions are named blocks of code that do specific work. This function is called to perform a specific task defined by the function. By using functions, programs are easier to write, read, test, and fix.

Define a function

  • Here is a simple function for printing a greeting calledgreet_user():
def greet_user() :
    """ Display a simple greeting. ""
    print("Hello!")

greet_user()
Copy the code

Passing information to a function

def greet_user(username) :
    """ Display a simple greeting. ""
    print(f"Hello, {username}")

greet_user("jesse")
Copy the code

Arguments and parameters

  • In the functiongreet_user()In the definition of, variablesusernameIs a parameter, which is the information a function needs to do its job.
  • In the codegreet_user('jesse')The value ofjesseIs an argument, which is the information passed to a function when it is called.

Pass arguments

  • There are many ways to pass arguments to a function: positional arguments can be used, which requires that the arguments be in the same order as the parameters; You can also use keyword arguments, where each argument consists of a variable name and value; You can also use lists and dictionaries.

Position the arguments

  • When using a function, Python must associate 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 arguments. Such associations are called positional arguments.
def describe_pet(animal_type, pet_name) :
    """ Displays pet information." ""
    print(f"I have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet('hamster'.'harry')
Copy the code
  1. Calling a function multiple times
    • You can call the function as many times as you need.
  2. The order of positional arguments is important
    • When you call a function with positional arguments, the results can be unexpected if the arguments are not in the right order.
    • The order of arguments in a function call is the same as the order of parameters in the function definition.

Keyword argument

  • The keyword argument is the name-value pair passed to the function.
  • To associate names and values directly in arguments, there is no confusion when passing arguments to functions.
def describe_pet(animal_type, pet_name) :
    """ Displays pet information." ""
    print(f"I have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet(animal_type='hamster', pet_name='harry')
Copy the code
  • The order of the keyword arguments doesn’t matter, because Python knows which parameter to assign each value to.

The default value

  • When writing a function, you can specify a default value for each parameter.
  • When a parameter is given an argument in a call to a function, Python uses the specified argument value; Otherwise, the default value of the parameter is used.
def describe_pet(pet_name, animal_type='dog') :
    """ Displays pet information." ""
    print(f"I have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

describe_pet(pet_name='harry')
Copy the code

Equivalent function call

  • Given that positional arguments, keyword arguments, and default values can be mixed, there are usually multiple equivalent function calls.

Avoid argument errors

  • You will get a parameter mismatch error when you provide more or less information than the function needs to do its job.

The return value

  • A function does not always display the output directly; it can also process some data and return one or a set of values.
  • The value returned by a function is called the return value.
  • In a function, you can usereturnStatement returns the value to the line of code calling the function.

Return simple value

  • Let’s look at a function that takes a first and last name and returns a clean first name:
def get_formatted_name(first_name, last_name) :
    """ Returns a neat name." ""
    full_name = f"{first_name} {last_name}"
    return full_name.title()

musician = get_formatted_name('jimi'.'hendrix')
print(musician)
Copy the code

Make the arguments optional

  • Sometimes, you need to make the arguments optional so that the user of the function can provide additional information only when necessary.
  • Default values can be used to make arguments optional.
def get_formatted_name(first_name, last_name, middle_name=' ') :
    """ Returns a neat name." ""
    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)
Copy the code

Return a dictionary

  • The function can return any type of value, including more complex data structures such as lists and dictionaries.
def build_person(first_name, last_name) :
    """ Returns a dictionary containing information about a person. ""
    person = {'first': first_name, 'last': last_name}

    return person

musician = build_person('jimi'.'hendrix')
print(musician)
Copy the code

Use a combination of functions andwhilecycle

def get_formatted_name(first_name, last_name) :
    """ Returns a neat name." ""
    full_name = f"{first_name} {last_name}"
    
    return full_name.title()

while True:
    print("Please 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"Hello, {formatted_name}!")
Copy the code

Transfer list

  • Once you pass the list to a function, the function has direct access to its contents.
def greet_users(names) :
    """ Send a simple greeting to each user on the list." ""
    for name in names:
        msg = f"Hello, {name.title()}!"
        print(msg)

usernames = ['hannah'.'ty'.'margot']

greet_users(usernames)
Copy the code

Modify the list in the function

  • After you pass the list to a function, the function can modify it. Any changes you make to this list in a function are permanent, allowing you to process large amounts of data efficiently.
  • Let’s look at a case where we don’t use a function:
unprinted_designs = ['phone case'.'robot pendant'.'dodecahedron']

completed_models = []

while unprinted_designs:
    current_design = unprinted_designs.pop()
    print(f"Printing model: {current_design}...")
    completed_models.append(current_design)

print("The following models have been printed:")

for completed_model in completed_models:
    print(completed_model)
Copy the code
  • Reorganize the code and add functions
def print_models(unprinted_designs, completed_models) :
    """ Simulate printing each design until there are no unprinted designs. As each design is printed, it is moved to the list Completed_Models. "" "
    while unprinted_designs:
        current_design = unprinted_designs.pop()
        print(f"Printing model: {current_design}...")
        completed_models.append(current_design)

def show_completed_models(completed_models) :
    """ Display all the printed models." ""
    print("The following models have been printed:")

    for completed_model in completed_models:
        print(completed_model)

unprinted_designs = ['phone case'.'robot pendant'.'dodecahedron']

completed_models = []

print_models(unprinted_designs, completed_models)

show_completed_models(completed_models)
Copy the code
  • The program also demonstrates the idea that each function should do only one specific job.

Disallow functions from modifying lists

  • Sometimes, you need to disallow functions from modifying lists.
  • Pass a copy of the list to the function instead of the original, so that changes made by the function only affect the copy, not the original.
  • To pass a copy of the list to a function, do something like this:
function_name(list_name[:])
Copy the code
  • Slicing notation creates a copy of the list.

Although passing a copy of the list to a function preserves the contents of the original list, you should pass the original list to the function unless there is a good reason to do so. This is because having functions use ready-made lists avoids the time and memory required to create copies, which increases efficiency, especially when working with large lists.

Pass any number of arguments

  • Sometimes you don’t know in advance how many arguments a function needs to take, but Python allows a function to collect any number of arguments from the calling statement.
def make_pizza(*toppings) :
    """ Print all the ingredients the customer ordered." ""
    print(toppings)

make_pizza('pepperoni')
make_pizza('mushrooms'.'green peppers'.'extra cheese')
Copy the code
  • Parameter name*toppingsIn theThe asteriskLet Python create a name calledtoppingsEmpty tuple, and encapsulates all values received into this tuple.
  • Now you can call the functionprint()Replace it with a loop that iterates through the list of ingredients and describes the pizza the customer ordered:
def make_pizza(*toppings) :
    """ Outline the pizza to be made." ""
    print("Making a pizza with the following toppings:")
    
    for topping in toppings:
        print(f"- {topping}")

make_pizza('pepperoni')
make_pizza('mushrooms'.'green peppers'.'extra cheese')
Copy the code

Use a combination of positional arguments and any number of arguments

  • If you want a function to accept different types of arguments, you must place the parameter that takes any number of arguments last in the function definition. Python matches positional and keyword arguments, and collects the remaining arguments into the last parameter.
  • For example, we also need to express the size of the pizza:
def make_pizza(size, *toppings) :
    """ Outline the pizza to be made." ""
    print(f"Making a {size}-inch pizza with the following toppings:")
    
    for topping in toppings:
        print(f"- {topping}")

make_pizza(16.'pepperoni')
make_pizza(12.'mushrooms'.'green peppers'.'extra cheese')
Copy the code

Use any number of keyword arguments

  • Sometimes, you need to take an arbitrary number of arguments without knowing in advance what information will be passed to the function.
  • In this case, the function can be written to accept any number of key-value pairs — as many as the calling statement provides.
def build_profile(first, last, **user_info) :
    "" create a dictionary that contains everything we know about the user. ""
    user_info['first_name'] = first
    user_info['last_name'] = last

    return user_info

user_profile = build_profile('albert'.'einstein',
                            location = 'princeton',
                            field = 'physics')
print(user_profile)
Copy the code
  • parameter**user_infoIn theTwo asterisksLet Python create a name calleduser_infoEmpty dictionary, and put all the name value pairs you receive into this dictionary.

Note that you will often see the parameter name **kwargs, which is used to collect any number of keyword arguments.

Store functions in modules

  • One of the advantages of using functions is that you can separate blocks of code from the main program. By giving descriptive names to functions, you make the main program much easier to understand. You can go one step further and store functions in separate files called modules, which you import into the main program.
  • importStatement allows code in a module to be used in the currently running program file.
  • By storing functions in separate files, you hide the details of your program code and focus on the higher-level logic of your program. This also allows you to reuse functions in many different programs.
  • Once you store functions in separate files, you can share those files with other programmers instead of the entire program. Knowing how to import functions also lets you use libraries written by other programmers.

Import the entire module

  • To make a function importable, create a module.
  • A module is an extension.pyContains the code to be imported into the program.
  • Start by creating a modulepizza.py
# pizza.py

def make_pizza(size, *toppings) :
    """ Outline the pizza to be made." ""
    print(f"Making a {size}-inch pizza with the following toppings:")
    
    for topping in toppings:
        print(f"- {topping}")
Copy the code
  • Second inmaking_pizza.pyTo import this file:
# making_pizza.py

import pizza

pizza.make_pizza(16.'pepperoni')
pizza.make_pizza(12.'mushrooms'.'green peppers'.'extra cheese')
Copy the code

Importing a specific function

  • You can import specific functions from specified modules
# making_pizza.py

from pizza import make_pizza

make_pizza(12.'mushrooms'.'green peppers'.'extra cheese')
make_pizza(16.'pepperoni')
Copy the code

useasAlias the function

  • The keywordasRename a function to the specified alias:
# making_pizza.py

from pizza import make_pizza as mp

mp()(12.'mushrooms'.'green peppers'.'extra cheese')
mp(16.'pepperoni')
Copy the code

useasGive the module an alias

# making_pizza.py

import pizza as p

p.make_pizza(12.'mushrooms'.'green peppers'.'extra cheese')
p.make_pizza(16.'pepperoni')
Copy the code

Import all functions in the module

  • Use the asterisk*The operator lets Python import all functions in a module:
# making_pizza.py

from pizza import *

make_pizza(12.'mushrooms'.'green peppers'.'extra cheese')
make_pizza(16.'pepperoni')
Copy the code
  • When working with large modules that you did not write yourself, it is best not to use this method of import. This is because if there are functions in a module with the same name as those used in the current project, this can lead to unexpected results: Python may encounter multiple functions or variables with the same name and override the functions instead of importing them all separately.
  • The best practice is to either import only the functions you need to use, or import the entire module and use period notation.

Function writing Guide

  • You should give functions descriptive names and use only lowercase letters and underscores in them.
  • You should also follow this convention when naming your modules.
  • Each function should include comments that briefly explain its functionality.
  • Comments should follow the function definition and be in docstring format.
  • When specifying a default value for a parameter, do not have Spaces on either side of the equal sign; This convention should also be followed for keyword arguments in function calls.
  • allimportStatements should be placed at the beginning of the file. Except for the comments at the beginning of the file that describe the entire program.