Getting Started with Python (16) Functions (4)

Author: Xiou

1. Pass the list

We often find it useful to pass lists to functions, which may contain names, numbers, or more complex objects such as dictionaries. When a list is passed to a function, the function can directly access its contents. The following uses functions to improve the efficiency of processing lists.

Suppose we have a list of users and we want to greet each of them. The following example passes a list of names to a function called greet_users() that greets everyone in the list:

  def greet_users(names):
      """向列表中的每位用户发出简单的问候。"""
      for name in names:
          msg = f"Hello, {
      
      name.title()}!"
          print(msg)

  usernames = ['hannah', 'ty', 'margot']
  greet_users(usernames)

We define greet_users() to accept a list of names and assign it to the formal parameter names. This function iterates through the received list and prints a greeting for each user in it. Define a list of users usernames , then call greet_users() passing it the list:

insert image description here

The output is exactly as expected. Each user sees a personalized greeting. This function can be called whenever a group of users needs to be greeted.

1.1 Modifying a list in a function

Once a list is passed to a function, it can be modified by the function. Any modifications made to this list within the function are permanent, allowing you to efficiently process large amounts of data.

Meet a company that makes 3D printed models of user-submitted designs. Designs that need to be printed are stored in one list and moved to another list after printing. Here is the code to simulate this process without using functions:

# 首先创建一个列表,其中包含一些要打印的设计。
unprinted_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_models = []

# 模拟打印每个设计,直到没有未打印的设计为止。
# 打印每个设计后,都将其移到列表completed_models中。
while unprinted_designs:
    current_design = unprinted_designs.pop()
    print(f"Printing model: {
      
      current_design}")
    completed_models.append(current_design)

# 显示打印好的所有模型。
print("\nThe following models have been printed:")
for completed_model in completed_models:
    print(completed_model)

This program first creates a list of designs that need to be printed, and an empty list called completed_models into which each design will be moved as it is printed. As long as there are designs in the list unprinted_designs, the while loop simulates the process of printing designs: removes a design from the end of the list, assigns it to the variable current_design, displays a message that the current design is being printed, then adds the design to the list completed_models. After the loop finishes, display all designs that were printed:

insert image description here
To reorganize this code, write two functions, each doing a specific job. Most of the code is the same as before, just more efficient. The first function handles the work of printing the designs, the second gives an overview of which designs were printed:

  def print_models(unprinted_designs, completed_models):
      """
      模拟打印每个设计,直到没有未打印的设计为止。
      打印每个设计后,都将其移到列表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):
      """显示打印好的所有模型。"""
      print("\nThe 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)

The function print_models() is defined, which contains two formal parameters: a list of designs to be printed and a list of printed models. Given these two lists, the function simulates the process of printing each design by taking designs one by one from the list of unprinted designs and adding them to the list of printed models.

The function show_completed_models() is defined, which contains a formal parameter: the list of printed models. Given this list, the function show_completed_models() displays the name of each model printed out.

The output of this program is the same as the version without functions, but more organized. The code that does most of the work has been moved into two functions to make the main program easier to understand. Just looking at the main program, it becomes much clearer what this program does:

insert image description here

We created a list of unprinted designs and an empty list to store the printed models. Next, since the two functions are already defined, it's just a matter of calling them and passing in the correct arguments. We call print_models() and pass it two lists. As expected, print_models() simulates the process of printing designs. Next, call show_completed_models(), passing it the list of printed models so it can indicate which models were printed. Descriptive function names make it understandable to someone reading the code, even without any comments.

2. Pass any number of arguments

Sometimes, it is not known in advance how many actual parameters the function needs to accept, but fortunately, Python allows functions to collect any number of actual parameters from the calling statement.

For example, consider a function that makes a pizza that accepts many toppings, but cannot predetermine how many toppings the customer will order. The following function has only one formal parameter *toppings, but no matter how many actual parameters are provided by the calling statement, this formal parameter will include them all:

def make_pizza(*toppings):
    """打印顾客点的所有配料。"""
    print(toppings)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

The asterisk in the formal parameter name *toppings tells Python to create an empty tuple named toppings and wrap all received values ​​into this tuple. The function call print() in the body of the function demonstrates that Python can handle the case of calling the function with one value, as well as the case of calling the function with three values, by producing output. It handles different calls in a similar manner. Note that Python wraps the arguments into a tuple, even if the function only receives a single value:

insert image description here

Now, the function call to print() can be replaced with a loop that iterates through the list of ingredients and describes the pizza the customer ordered:

def make_pizza(*toppings):
    """概述要制作的比萨。"""
    print("\nMaking a pizza with the following toppings:")
    for topping in toppings:
        print(f"- {
      
      topping}")

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

Whether it receives one value or three values, this function handles it gracefully:

insert image description here

This syntax works no matter how many arguments the function receives.

2.1 Combining positional and arbitrary number arguments

If you want a function to accept arguments of different types, you must place the formal parameter that takes any number of arguments last in the function definition. Python matches positional and keyword arguments first, then collects the remaining arguments into the last formal parameter.

For example, if the previous function also requires a parameter representing the size of the pizza, it must be placed before the parameter *toppings:

def make_pizza(size, *toppings):
    """概述要制作的比萨。"""
    print(f"\nMaking 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')

Based on the above function definition, Python assigns the first value received to the formal parameter size, and stores all other values ​​in the tuple toppings. In the function call, first specify the actual parameter representing the size of the pizza, and then specify any number of toppings as needed.

Each pizza now has dimensions and a list of toppings, and the information is printed in the correct order—first the dimensions, then the toppings:

insert image description here

2.2 Using any number of keyword arguments

Sometimes it is necessary to accept an arbitrary number of arguments, but it is not known 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. One such example is creating a user profile: you know you will receive information about the user, but are not sure what it will be like. In the example below, the function build_profile() accepts a first and last name, and any number of keyword arguments:

  def build_profile(first, last, **user_info):
      """创建一个字典,其中包含我们知道的有关用户的一切。"""
      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)

The function build_profile() is defined to require a first and last name, while allowing any number of name-value pairs to be provided as desired. The two asterisks in the formal parameter **user_info tell Python to create an empty dictionary named user_info and place all name-value pairs it receives into this dictionary. In this function, the name-value pairs in user_info can be accessed like any other dictionary.

In the function body of build_profile(), the first name and last name are added to the dictionary user_info, because these two pieces of information are always received from the user, and these two pieces of information are not put in this dictionary. Next, return the dictionary user_info to the function call line.

We call build_profile(), passing it the first name ('albert'), last name ('einstein'), and two key-value pairs (location='princeton' and field='physics'), and assign the returned user_info to the variable user_profile, and then print the variable:

insert image description here

Here, the returned dictionary contains the user's first and last name, as well as where they studied and what they majored in. When this function is called, no matter how many additional key-value pairs are provided, it will be processed correctly.

When writing functions, you can mix positional arguments, keyword arguments, and any number of arguments in various ways. It's helpful to know these argument types, because you'll see them all the time when you read code written by others. It takes some practice to use these types of arguments correctly and when to use them. For now, just remember to use the easiest way to get things done. Read on to find out which method is most efficient in each case.

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

Guess you like

Origin blog.csdn.net/qq_41600018/article/details/130957353