Review
知识点回顾:
1.函数的定义
函数将程序中的部分高频使用代码封装起来,通过一次编写即可完成多次调用的目的,减少了代码量
2.变量作用域:局部变量和全局变量。
全局变量是程序运行的整个过程中都可访问的变量,而局部变量是定义在一个作用范围内的(如函数内部的局部变量),只能在函数内部使用,在函数外部不可使用
3.函数的参数类型:位置参数、默认参数、不定参数
位置参数,如定义函数时
def func(a, b)
,调用时func(2, 3)
和func(3, 2)
是不同的,位置参数严格按照顺序传递。默认参数,如定义函数时
def func(a, b=2)
,调用函数func(1)
等效于func(1, 2)
,因为函数在定义时允许参数b不传,默认b为2不定参数,接收任意数量参数的参数,分两类,一类是
*args
,另一类是**kwargs
。*args
接受元组形式的位置参数(处理不定数量位置参数,传入的参数被打包成元组,位置唯一,不可修改)
**kwargs
接收字典形式的关键字参数(处理不定数量的关键字参数)
e.g.*args
def introduction(name, *args): return f"{name} 的技能有: {'. '.join(args)}" print(introduction("NeoFii", "Python", "Machine Learning"))
output:
'NeoFii 的技能有: Python. Machine Learning'
e.g.
**kwargs
def intro(**kwargs):
return "\n".join([f"{key}: {value}" for key, value in kwargs.items()])
print(intro(name="NeoFii", grade=3, gender="male"))
output:
name: NeoFii
grade: 3
gender: male
4.传递参数的手段:关键词参数
关键字参数传参能够无视顺序参数的限制,显式的通过关键字赋值并传参
5.传递参数的顺序:同时出现三种参数类型时
函数定义的参数规范,多个不同参数类型传参时严格按照下面的参数顺序进行传参
def func(
位置参数, # 必须参数
默认参数=值, # 可选参数
*args, # 接收多余位置参数
仅关键字参数, # 必须用关键字指定
**kwargs # 接收多余关键字参数
)
Today
今天的主要任务是函数的定义与使用。
作业:
题目1:计算圆的面积
- 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 = π * radius² (可以使用 math.pi 作为 π 的值)
- 要求:函数接收一个位置参数 radius。计算半径为5、0、-1时候的面积
- 注意点:可以采取try-except 使函数变得更加稳健,如果传入的半径为负数,函数应该返回 0 (或者可以考虑引发一个ValueError,但为了简单起见,先返回0)。
import math
def calculate_circle_area(radius):
try:
if radius <= 0:
raise ValueError("半径必须为非负数")
if not isinstance(radius, (int, float)):
raise TypeError("半径必须是数字")
res = math.pi * radius ** 2
return f"圆的面积为: {res}"
except TypeError as te:
print(f"Input Error: {te}")
except ValueError as ve:
print(f'Input Error: {ve}')
except Exception as e:
print(f'Error: {e}')
print(f"半径为5的面积: {calculate_circle_area(5)}") # 正常情况
print('\n')
print(f"输入None的面积: {calculate_circle_area(None)}") # 特殊值情况
print('\n')
print(f"半径为0的面积: {calculate_circle_area(0)}") # 边界情况
print('\n')
print(f"半径为-1的面积: {calculate_circle_area(-1)}") # 负数情况
print('\n')
print(f"输入字符串的面积: {calculate_circle_area('abc')}") # 非数字情况
半径为5的面积: 圆的面积为: 78.53981633974483
Input Error: '<=' not supported between instances of 'NoneType' and 'int'
输入None的面积: None
Input Error: 半径必须为非负数
半径为0的面积: None
Input Error: 半径必须为非负数
半径为-1的面积: None
Input Error: '<=' not supported between instances of 'str' and 'int'
输入字符串的面积: None
题目2:计算矩形的面积
- 任务: 编写一个名为 calculate_rectangle_area 的函数,该函数接收矩形的长度 length 和宽度 width 作为参数,并返回矩形的面积。
- 公式: 矩形面积 = length * width
- 要求:函数接收两个位置参数 length 和 width。
- 函数返回计算得到的面积。
- 如果长度或宽度为负数,函数应该返回 0。
def calculate_rectangle_area(length, width):
try:
# 验证输入是否为数字类型
if not (isinstance(length, (int, float)) or not (isinstance(width, (int, float))):
raise TypeError("长度和宽度必须是数字")
# 验证非负性
if length < 0 or width < 0:
raise ValueError(f"长度({length})或宽度({width})为负数")
# 计算并返回面积
area = length * width
return area
except TypeError as te:
print(f"错误: {te}")
return 0
except ValueError as ve:
print(f"警告: {ve},面积无效")
return 0
except Exception as e:
print(f"意外错误: {e}")
return 0
# 测试用例
print("测试1 (正常):", calculate_rectangle_area(5, 3)) # 15
print("测试2 (负长度):", calculate_rectangle_area(-2, 4)) # 0
print("测试3 (负宽度):", calculate_rectangle_area(6, -1)) # 0
print("测试4 (双负数):", calculate_rectangle_area(-3, -2)) # 0
print("测试5 (零值):", calculate_rectangle_area(0, 7)) # 0
print("测试6 (字符串):", calculate_rectangle_area("5", 3)) # 0
print("测试7 (小数):", calculate_rectangle_area(2.5, 4.0)) # 10.0
print("测试8 (None):", calculate_rectangle_area(None, 4)) # 0
测试1 (正常): 15
警告: 长度(-2)或宽度(4)为负数,面积无效
测试2 (负长度): 0
警告: 长度(6)或宽度(-1)为负数,面积无效
测试3 (负宽度): 0
警告: 长度(-3)或宽度(-2)为负数,面积无效
测试4 (双负数): 0
测试5 (零值): 0
错误: 长度和宽度必须是数字
测试6 (字符串): 0
测试7 (小数): 10.0
错误: 长度和宽度必须是数字
测试8 (None): 0
题目3:计算任意数量数字的平均值
- 任务: 编写一个名为 calculate_average 的函数,该函数可以接收任意数量的数字作为参数(引入可变位置参数 (*args)),并返回它们的平均值。
- 要求:使用 *args 来接收所有传入的数字。
- 如果没有任何数字传入,函数应该返回 0。
- 函数返回计算得到的平均值。
def calculate_average(*numbers):
try:
# 检查是否有数字传入
if len(numbers) == 0:
return 0
# 验证所有输入都是数字
for num in numbers:
if not isinstance(num, (int, float)):
raise TypeError(f"所有参数必须是数字,检测到无效类型: {type(num).__name__}")
# 计算总和和平均值
total = sum(numbers)
average = total / len(numbers)
return average
except TypeError as te:
print(f"计算错误: {te}")
return 0
except ZeroDivisionError:
# 理论上不会发生,因为已经检查了len(numbers)==0的情况
return 0
except Exception as e:
print(f"意外错误: {e}")
return 0
# 测试用例
print("测试1 (整数):", calculate_average(2, 4, 6)) # 4.0
print("测试2 (混合):", calculate_average(1, 2.5, 3, 4.5)) # 2.75
print("测试3 (单数):", calculate_average(10)) # 10.0
print("测试4 (空):", calculate_average()) # 0
print("测试5 (小数):", calculate_average(0.1, 0.2, 0.3)) # 0.2
print("测试6 (含字符串):", calculate_average(1, 2, "three")) # 0
print("测试7 (含None):", calculate_average(5, None, 10)) # 0
测试1 (整数): 4.0
测试2 (混合): 2.75
测试3 (单数): 10.0
测试4 (空): 0
测试5 (小数): 0.2
计算错误: 所有参数必须是数字,检测到无效类型: str
测试6 (含字符串): 0
计算错误: 所有参数必须是数字,检测到无效类型: NoneType
测试7 (含None): 0
题目4:打印用户信息
- 任务: 编写一个名为 print_user_info 的函数,该函数接收一个必需的参数 user_id,以及任意数量的额外用户信息(作为关键字参数)。
- 要求:
- user_id 是一个必需的位置参数。
- 使用 **kwargs 来接收额外的用户信息。
- 函数打印出用户ID,然后逐行打印所有提供的额外信息(键和值)。
- 函数不需要返回值
def print_user_info(user_id, **kwargs):
# 打印必需的用户ID
print(f"用户ID: {user_id}")
# 检查是否有额外信息
if not kwargs:
print("无额外用户信息")
return
# 打印额外信息
print("额外用户信息:")
for key, value in kwargs.items():
print(f" - {key}: {value}")
# 测试用例
print("===== 测试1: 基本使用 =====")
print_user_info("A123", name="张三", age=30, email="zhang@example.com")
print("\n===== 测试2: 只有必需参数 =====")
print_user_info("B456")
print("\n===== 测试3: 多种数据类型 =====")
print_user_info("C789",
is_vip=True,
scores=[95, 88, 92],
address={"city": "北京", "street": "长安街"},
last_login="2023-10-05")
print("\n===== 测试4: 特殊字符处理 =====")
print_user_info("D#001",
full_name="Li Si",
"职位"="工程师", # 注意:包含中文键名
remarks="特殊字符: @#$%")
===== 测试1: 基本使用 =====
用户ID: A123
额外用户信息:
- name: 张三
- age: 30
- email: zhang@example.com
===== 测试2: 只有必需参数 =====
用户ID: B456
无额外用户信息
===== 测试3: 多种数据类型 =====
用户ID: C789
额外用户信息:
- is_vip: True
- scores: [95, 88, 92]
- address: {'city': '北京', 'street': '长安街'}
- last_login: 2023-10-05
===== 测试4: 特殊字符处理 =====
用户ID: D#001
额外用户信息:
- full_name: Li Si
- 职位: 工程师
- remarks: 特殊字符: @#$%
题目5:格式化几何图形描述
- 任务: 编写一个名为 describe_shape 的函数,该函数接收图形的名称 shape_name (必需),一个可选的 color (默认 “black”),以及任意数量的描述该图形尺寸的关键字参数 (例如 radius=5 对于圆,length=10, width=4 对于矩形)。
- 要求:shape_name 是必需的位置参数。
- color 是一个可选参数,默认值为 “black”。
- 使用 **kwargs 收集描述尺寸的参数。
- 函数返回一个描述字符串,格式如下:
- “A [color] [shape_name] with dimensions: [dim1_name]=[dim1_value], [dim2_name]=[dim2_value], …”如果 **kwargs 为空,则尺寸部分为 “with no specific dimensions.”
desc1 = describe_shape("circle", radius=5, color="red")
print(desc1)
# 输出: A red circle with dimensions: radius=5
desc2 = describe_shape("rectangle", length=10, width=4)
print(desc2)
# 输出: A black rectangle with dimensions: length=10, width=4
desc3 = describe_shape("triangle", base=6, height=8, color="blue")
print(desc3)
# 输出: A blue triangle with dimensions: base=6, height=8
desc4 = describe_shape("point", color="green")
print(desc4)
# 输出: A green point with no specific dimensions.
def describe_shape(shape_name, color="black", **dimensions):
# 基础描述部分
description = f"A {color} {shape_name}"
# 添加尺寸描述
if dimensions:
# 格式化为 "key1=value1, key2=value2" 的形式
dim_str = ", ".join([f"{k}={v}" for k, v in dimensions.items()])
description += f" with dimensions: {dim_str}"
else:
description += " with no specific dimensions."
return description
# 测试用例
desc1 = describe_shape("circle", radius=5, color="red")
print(desc1) # A red circle with dimensions: radius=5
desc2 = describe_shape("rectangle", length=10, width=4)
print(desc2) # A black rectangle with dimensions: length=10, width=4
desc3 = describe_shape("triangle", base=6, height=8, color="blue")
print(desc3) # A blue triangle with dimensions: base=6, height=8
desc4 = describe_shape("point", color="green")
print(desc4) # A green point with no specific dimensions.
# 额外测试
desc5 = describe_shape("square", side=7)
print(desc5) # A black square with dimensions: side=7
desc6 = describe_shape("cube", edge_length=3, color="yellow")
print(desc6) # A yellow cube with dimensions: edge_length=3
desc7 = describe_shape("sphere", radius=10)
print(desc7) # A black sphere with dimensions: radius=10
desc8 = describe_shape("line")
print(desc8) # A black line with no specific dimensions.
A red circle with dimensions: radius=5
A black rectangle with dimensions: length=10, width=4
A blue triangle with dimensions: base=6, height=8
A green point with no specific dimensions.
A black square with dimensions: side=7
A yellow cube with dimensions: edge_length=3
A black sphere with dimensions: radius=10
A black line with no specific dimensions.