Day 26 函数专题1:函数定义与参数

发布于:2025-07-31 ⋅ 阅读:(20) ⋅ 点赞:(0)

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.

@浙大疏锦行


网站公告

今日签到

点亮在社区的每一天
去签到