提示:
1. 8.函数
8.1 定义函数
函数的定义是指创建一个具有特定功能的代码块。在大多数编程语言(如Python)中,定义函数的基本语法如下:
def 函数名(参数):
函数体(实现功能的代码)
return 返回值(可选)
例如,定义一个计算两数之和的函数:
def add(a, b):
result = a + b
return result
8.1.1 向函数传递信息
函数可以通过参数接收外部传递的信息,从而实现更灵活的功能。参数就像函数的“输入”,让函数可以根据不同的输入执行不同的操作。
例如,上述add函数中的a和b就是接收外部信息的参数,调用时可以传入不同的数值:add(3, 5)会计算3+5,add(10, 20)会计算10+20。
8.1.2 实参和形参
- 形参(形式参数):函数定义时括号中声明的参数,是函数内部用于接收信息的“占位符”。例如
add(a, b)中的a和b就是形参。 - 实参(实际参数):函数调用时传入的具体值,用于填充形参。例如
add(3, 5)中的3和5就是实参。
简单来说,形参是“函数定义时写的参数名”,实参是“函数调用时传的具体值”。
8.2 传递实参
调用函数时,需要将实参传递给形参,传递方式有多种,目的是确保实参与形参正确匹配。
8.2.1 位置实参
最常见的传递方式,实参的顺序与形参的顺序完全一致。例如:
def describe_pet(animal_type, pet_name):
print(f"I have a {animal_type} named {pet_name}.")
# 位置实参:第一个实参对应第一个形参,第二个对应第二个
describe_pet("dog", "Buddy") # 输出:I have a dog named Buddy.
如果顺序错误,结果会不符合预期:describe_pet("Buddy", "dog")会输出“I have a Buddy named dog.”,显然不合理。
8.2.2 关键字实参
通过“形参名=实参值”的形式传递,不需要考虑顺序,直接指定实参对应的形参。例如:
# 关键字实参:明确指定实参对应的形参,顺序无关
describe_pet(animal_type="cat", pet_name="Luna")
describe_pet(pet_name="Momo", animal_type="rabbit") # 顺序颠倒也不影响
两种方式的输出都是“I have a cat named Luna.”和“I have a rabbit named Momo.”。
8.2.3 默认值
可以在定义函数时给形参指定默认值,调用时如果不传递该参数,则使用默认值。例如:
# 给animal_type设置默认值"dog"
def describe_pet(pet_name, animal_type="dog"):
print(f"I have a {animal_type} named {pet_name}.")
# 不传递animal_type,使用默认值"dog"
describe_pet("Buddy") # 输出:I have a dog named Buddy.
# 传递animal_type,覆盖默认值
describe_pet("Luna", "cat") # 输出:I have a cat named Luna.
注意:设置默认值的形参通常放在无默认值形参的后面。
8.2.4 等效的函数调用
通过位置实参、关键字实参和默认值的组合,可以用多种方式调用同一个函数,只要实参与形参能正确匹配,结果就是等效的。例如对于上述describe_pet函数:
describe_pet("Buddy") # 位置实参(仅传pet_name,animal_type用默认值)
describe_pet(pet_name="Buddy") # 关键字实参(仅传pet_name)
describe_pet("Momo", "rabbit") # 位置实参(传两个参数)
describe_pet(animal_type="rabbit", pet_name="Momo") # 关键字实参(传两个参数)
以上调用的效果完全一致。
8.2.5 避免实参错误
如果传递的实参数量与形参不匹配,或无法正确匹配,会导致错误。例如:
# 形参需要2个,但只传1个实参,会报错
describe_pet("Buddy") # 如果函数没有默认值,这里会报错:缺少1个位置实参
调用时需确保实参数量、类型与形参匹配。
8.3 返回值
函数执行完成后,可以通过return语句将结果返回给调用者,这个结果就是返回值。
8.3.1 返回简单的值
最基础的返回方式,直接返回一个数值、字符串等。例如:
def get_full_name(first_name, last_name):
full_name = f"{first_name} {last_name}"
return full_name # 返回拼接后的字符串
name = get_full_name("Alice", "Smith")
print(name) # 输出:Alice Smith
8.3.2 让实参变成可选的
通过给形参设置默认值(如空字符串),让实参可选。例如,处理中间名:
def get_full_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
print(get_full_name("John", "Doe")) # 输出:John Doe(中间名可选,未传递)
print(get_full_name("John", "Doe", "Michael")) # 输出:John Michael Doe(传递中间名)
8.3.3 返回字典
函数可以返回复杂数据类型,如字典,用于封装多个相关值。例如:
def build_person(name, age):
person = {"name": name, "age": age}
return person # 返回字典
person = build_person("Bob", 30)
print(person) # 输出:{'name': 'Bob', 'age': 30}
8.3.4 结合使用函数和 while 循环
函数可以与循环结合,实现重复调用函数的功能。例如,不断接收用户输入并处理:
在 Python 中,while True 是一个 无限循环 的写法,意思是:让循环体里的代码 一直重复执行,直到遇到 break 语句才会停止。
详细解释:
while 是 Python 的循环关键字,后面跟一个 条件表达式。当条件为 True 时,就会执行循环体里的代码;条件为 False 时,循环结束。
True 是 Python 中的布尔值,表示 “真”。所以 while True 就意味着 条件永远为真,循环会无限执行下去(除非用 break 强制退出)。
def greet_user(name):
return f"Hello, {name}!"
while True:
print("\nPlease tell me your name (enter 'quit' to stop):")
name = input()
if name == "quit":
break
print(greet_user(name)) # 循环中调用函数
8.4 传递列表
函数可以接收列表作为实参,便于批量处理数据。
8.4.1 在函数中修改列表
函数接收列表后,可以直接修改列表中的元素,且修改会影响原列表(因为列表是“可变对象”)。例如:
def process_messages(messages, sent_messages):
while messages:
current_message = messages.pop() # 从messages中取出最后一条消息
print(f"Sending: {current_message}")
sent_messages.append(current_message) # 添加到已发送列表
messages = ["Hello!", "How are you?", "Goodbye!"]
sent_messages = []
process_messages(messages, sent_messages)
print("Original messages:", messages) # 输出:Original messages: [](原列表被修改)
print("Sent messages:", sent_messages) # 输出:Sent messages: ['Goodbye!', 'How are you?', 'Hello!']
8.4.2 禁止函数修改列表
如果希望函数不修改原列表,可以传递列表的副本(通过列表名[:]创建)。例如:
# 传递messages的副本,原列表不会被修改
process_messages(messages[:], sent_messages)
print("Original messages:", messages) # 输出:Original messages: ["Hello!", "How are you?", "Goodbye!"](原列表未变)
8.5 传递任意数量的实参
当不确定需要传递多少个实参时,可以使用“任意数量的实参”功能。
8.5.1 结合使用位置实参和任意数量的实参
在形参前加*,表示接收任意数量的位置实参,这些实参会被封装成一个元组。例如:
# *toppings接收任意数量的实参,封装成元组
def make_pizza(size, *toppings):
print(f"Making a {size}-inch pizza with the following toppings:")
for topping in toppings:
print(f"- {topping}")
# 调用时,第一个实参是size(位置实参),后面的都是toppings(任意数量)
make_pizza(12, "pepperoni", "mushrooms")
make_pizza(16, "cheese", "onions", "sausage", "bell peppers")
8.5.2 使用任意数量的关键字实参
在形参前加**,表示接收任意数量的关键字实参,这些实参会被封装成一个字典。例如:
# **user_info接收任意数量的关键字实参,封装成字典
def build_profile(first, last,** user_info):
profile = {"first_name": first, "last_name": last}
## 6.3.1 遍历所有的键值对-items()方法
# 使用items()方法可返回字典中所有键值对的视图,配合for循环遍历:
for key, value in user_info.items():
profile[key] = value # 添加额外信息
return profile
# 调用时,前两个是位置实参,后面的是关键字实参(任意数量)
user_profile = build_profile("albert", "einstein", location="princeton", field="physics")
print(user_profile)
# 输出:{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
8.6 将函数存储在模块中
为了代码的整洁和复用,可以将函数存储在独立的文件(称为“模块”)中,然后在其他程序中导入使用。
8.6.1 导入整个模块
模块是一个.py文件,例如my_functions.py中定义了add和subtract函数。导入整个模块的语法:
import my_functions # 导入整个模块
# 使用模块中的函数:模块名.函数名()
result1 = my_functions.add(3, 5)
result2 = my_functions.subtract(10, 4)
8.6.2 导入特定的函数
只导入模块中需要的函数,语法:
from my_functions import add, subtract # 只导入add和subtract
# 直接使用函数名,无需加模块名
result1 = add(3, 5)
result2 = subtract(10, 4)
8.6.3 使用 as 给函数指定别名
如果函数名较长或与现有名称冲突,可以用as指定别名:
from my_functions import add as a # 给add起别名a
result = a(3, 5) # 用别名调用
8.6.4 使用 as 给模块指定别名
给模块起简短的别名,方便调用:
import my_functions as mf # 给模块起别名mf
result = mf.add(3, 5) # 用模块别名调用函数
8.6.5 导入模块中的所有函数
使用*导入模块中所有函数(不推荐,可能导致名称冲突):
from my_functions import * # 导入所有函数
result1 = add(3, 5)
result2 = subtract(10, 4)
8.7 函数编写指南
为了写出规范、易读的函数,通常需要遵循以下指南:
- 函数名应使用小写字母,多个单词用下划线连接(如
get_full_name),清晰描述函数功能。 - 形参名也应简洁明了,如
pet_name比pn更易理解。 - 函数定义后,建议添加文档字符串(docstring),用
"""包裹,说明函数功能、参数、返回值等。例如:def add(a, b): """计算两个数的和并返回结果。 参数: a:第一个加数 b:第二个加数 返回: 两数之和 """ return a + b - 函数功能应单一,一个函数只做一件事,便于复用和维护。
- 避免在函数中使用全局变量,尽量通过参数传递数据,通过返回值输出结果。
8.8 小结
- 函数通过
def定义,用于封装可重复使用的代码。 - 形参是函数定义时的占位符,实参是调用时传递的具体值。
- 实参传递方式包括位置实参、关键字实参,可结合默认值使用。
- 函数可以返回值(简单值、字典等),也可以处理列表等数据结构。
- 支持传递任意数量的实参(
*接收位置实参,**接收关键字实参)。 - 函数可存储在模块中,通过导入实现代码复用。
- 遵循编写指南能提高函数的可读性和可维护性。
函数是编程中实现代码模块化、复用和抽象的重要工具,掌握函数的使用是学好编程的关键一步。
总结


被折叠的 条评论
为什么被折叠?



