第八章 函数

8.1 定义函数

一个简单的函数

def greet_user():
    '''显示简单的问候语'''
    print('Hello!')
    
greet_user()
'''
输出:
Hello!

'''

8.1.1 向函数传递信息

def greet_user(username):
    # 显示简单的问候语
    print(f'Hello, {username.title()}.')

greet_user('jesse')
greet_user('jim')
'''
输出:
Hello, Jesse.
Hello, Jim.

'''

8.1.2 形参和实参

上述代码中,变量username 就是形参,值 ‘jesse’ 和 ‘jim’ 就是实参

8.2 传递参数

函数定义中可能包括多个形参,函数调用时也可能包括多个实参,向函数传递实参的方法有:位置实参、关键字实参

8.2.1 位置实参

调用函数时,根据参数位置将实参关联到形参

def describe_pet(animal_type, pet_name):
    '''显示宠物信息'''
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name}.")

describe_pet('mouse', 'Micky')
describe_pet('dog', 'Harry')
describe_pet('Harry', 'dog')
'''

I have a mouse.
My mouse's name is Micky.

I have a dog.
My dog's name is Harry.

I have a Harry.
My Harry's name is dog.

'''
  1. 多次调用函数
  2. 位置实参的顺序很重要,第二次和第三次调用就说明了这个问题

8.2.2 关键字实参

关键字实参直接在实参中将名称和值关联起来,这样可以不考虑实参顺序

def describe_pet(animal_type, pet_name):
    '''显示宠物信息'''
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name}.")

describe_pet(animal_type = 'mouse',pet_name = 'Micky')
describe_pet(pet_name = 'Micky', animal_type = 'mouse')

'''
输出:

I have a mouse.
My mouse's name is Micky.

I have a mouse.
My mouse's name is Micky.

进程已结束,退出代码为 0

'''

8.2.3 默认值

编写函数时,可以给形参指定默认值,在调用函数时,给形参提供了实参时,程序将使用提供的实参,否则将使用形参的默认值
这里需要注意,一定要考虑参数位置(这里,形参-默认值也占据一个形参位置)

def describe_pet(pet_name, animal_type = 'mouse'):
    '''显示宠物信息'''
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name}.")

describe_pet('Micky')
describe_pet(pet_name = 'Harry', animal_type = 'dog')

'''
输出:

I have a mouse.
My mouse's name is Micky.

I have a dog.
My dog's name is Harry.
'''

8.2.4 等效的函数调用

可以混合使用位置参数、关键字参数和默认值

8.2.5 避免实参错误

8.3 返回值

函数可以使用 return 语句返回一个或者一组值

8.3.1 返回简单值

def get_formatted_name(first_name, last_name):
    '''返回整洁的姓名'''
    full_name = f"{first_name} {last_name}"
    return full_name.title()

musician = get_formatted_name('jim', 'hendrix')
print(musician)
'''
输出:
Jim Hendrix

'''

8.3.2 让实参变成可选的

并非所有人都有中间名,如果要让中间名变成可选的,可以将中间名移到参数最后,采用默认值的方法

def get_formatted_name(first_name, last_name, middle_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('jim', 'hendrix')
print(musician)
musician = get_formatted_name('john', 'hooker', 'lee')
print(musician)

'''
输出:
Jim Hendrix
John Lee Hooker

'''

8.3.3 返回字典

def build_person(first_name, last_name):
    person = {'first': first_name, 'last': last_name}
    return person

musician = build_person('jim', 'hendrix')
print(musician)

'''
输出:
{'first': 'jim', 'last': 'hendrix'}

'''

8.3.4 结合使用函数和 while 循环

def get_formatted_name(first_name, last_name):
    '''返回整洁的姓名'''
    full_name = f"{first_name} {last_name}"
    return full_name.title()

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: zhang
Last name: xy

Hello, Zhang Xy!

Please tell me your name: 
(enter 'q' at any time to quit)
First name: wang
Last name: q

'''

8.4 传递列表

向函数传递一个列表

def greet_users(names):
    for name in names:
        msg = f"Hello, {name.title()}."
        print(msg)

usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
'''
输出:
Hello, Hannah.
Hello, Ty.
Hello, Margot.

'''

8.4.1 在函数中修改列表

将列表传递给函数后,可以对其进行修改,函数对列表的修改是永久性的
将未打印列表中的元素打印,打印完成的元素移到完成打印的列表中

常规程序:

unprint_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_designs = []

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

print("\nThe following models have been printed: ")
for completed_design in completed_designs:
    print(completed_design)

'''
输出:
Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case

The following models have been printed: 
dodecahedron
robot pendant
phone case

'''

优化代码(每一个函数尽量只做一件事情,这样效果更高,主函数也更加简洁;第一个函数负责打印和移动列表元素,第二个函数负责展示已打印的信息)

def print_modules(unprinted_designs, completed_designs):
    while unprinted_designs:
        current_design = unprint_designs.pop()
        print(f"Printing model: {current_design}")
        completed_designs.append(current_design)

def show_completed_designs(completed_designs):
    print("\nThe following models have been printed: ")
    for completed_design in completed_designs:
        print(completed_design)

unprint_designs = ['phone case', 'robot pendant', 'dodecahedron']
completed_designs = []

print_modules(unprint_designs, completed_designs)
show_completed_designs(completed_designs)

'''
输出:
Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case

The following models have been printed: 
dodecahedron
robot pendant
phone case

'''

8.4.2 禁止函数修改列表

其实不是严格意义上的禁止修改列表,而是将原列表上产生一个备份,在备份列表进行操作,这样就不影响原列表

function_name(list_name[:])

8.5 传递任意数量的参数

*toppings 中的星号让程序创建一个名为 toppings 的空元组,并将收到的所有值装入到这个元组中

def make_pizza(*toppings):
    print("\nMaking a pizza with the following toppings: ")
    for topping in toppings:
        print(f"- {topping}")

make_pizza('peperoni')
make_pizza('mushrooms', 'green peppers', 'extra chesese')

'''
输出:

Making a pizza with the following toppings: 
- peperoni

Making a pizza with the following toppings: 
- mushrooms
- green peppers
- extra chesese

'''

8.5.1 结合使用位置的实参和任意数量的实参

如果函数要接受不同类型的实参,必须将接纳任意数量实参的形参放在最后,这样,程序将先匹配位置参数,再将剩余的实参都收集到最后一个形参中,如果有默认关键字参数,可以放到最后

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, 'peperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra chesese')

'''
输出:

Making a 16-inch pizza with the following toppings: 
- peperoni

Making a 12-inch pizza with the following toppings: 
- mushrooms
- green peppers
- extra chesese

'''

8.5.2 使用任意数量的关键字实参

**user_info 用于收集任意数量的键值对

def build_profile(first, last, **user_info):
    user_info['first_name'] = first
    user_info['last_name'] = last
    return user_info
# 关键字实参直接以键值对的形式存储,非关键字实参改为键值对形式追加存储
user_proflie = build_profile('albert', 'einstein', location = 'princeton', field = 'physics')
print(user_proflie)

'''
输出:
{'location': 'princeton', 'field': 'physics', 'first_name': 'albert', 'last_name': 'einstein'}

'''

8.6 将函数存储在模块中

用 import 语句让当前程序使用模块中的代码,模块可以理解为独立文件,该文件中有很多好用的函数

8.6.1 导入整个模块

将 pizza.py 文件作为模块,在making_pizza.py 中调用该模块,使用模块中的函数使用的语法是:

module_name.function_name()

pizza.py 文件

def make_pizza(size, *toppings):
# pizza.py 模块,包含函数 make_pizza()
    print(f"\nMaking a {size}-inch pizza with the following toppings: ")
    for topping in toppings:
        print(f"- {topping}")

making_pizza.py 文件

import pizza

pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
'''
输出:

Making a 16-inch pizza with the following toppings: 
- pepperoni

Making a 12-inch pizza with the following toppings: 
- mushrooms
- green peppers
- extra cheese

'''

8.6.2 导入特定的函数

导入模块中特定的函数,语法如下:

from module_name import function_name

如果导入多个函数,用逗号分隔

from module_name import function0, function1, function2

在这种情况下,调用函数时,无需使用 . 运算符

from pizza import make_pizza

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
'''
输出:

Making a 16-inch pizza with the following toppings: 
- pepperoni

Making a 12-inch pizza with the following toppings: 
- mushrooms
- green peppers
- extra cheese

'''

8.6.3 使用 as 给函数指定别名

如果要导入的函数与程序中现有的名称冲突,或者函数的名称太长,就可以给函数取别名
语法如下:

from module_name import function_name as mp

上小节代码可以表示为

from pizza import make_pizza as mp

mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')

8.6.4 使用 as 给模块指定别名

还可以给模块指定别名,语法如下:

import module_name as mn

8.6.1 代码可以改写为:

import pizza as mn

mn.make_pizza(16, 'pepperoni')
mn.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

8.6.5 导入模块中的所有函数

语法如下:

from module_name import *

这种做法不推荐使用,建议使用

  1. 只导入需要使用的函数,不需要 . 运算符
  2. 导入整个模块,使用 . 运算符调用函数

8.7 函数编写指南

  1. 函数命名只用小写字母和下划线
  2. 函数的注释应紧跟在函数定义后面,并采用文档字符串格式
  3. 给形参指定默认值时,等号两边不要有空格

8.8 小结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张小勇zhangxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值