跳转至

第4章《函数与模块》

参考资料

hhu史秋实老师的ppt 点击这里查看或下载 PDF 文档

依据 第4章:函数与模块 设计,并结合前 1~3 章的知识: - 第1章:基础输入输出、变量、简单程序 - 第2章:数据类型、字符串、列表、字典、元组 - 第3章:顺序结构、选择结构、循环结构

结构如下: 1. 课堂例题展示(严格对应 PPT 知识点) 2. 20 道综合较难题(每题附参考解法) 3. 类 LeetCode Medium 的思维题

一、课堂例题展示

下面的例题一一对应的核心知识点: 1. 函数的定义与调用 2. 位置参数 3. 关键字参数 4. 默认值参数 5. 可变长参数 *args / **kwargs 6. 变量作用域(局部变量、全局变量) 7. 递归函数 8. lambda 匿名函数 9. 模块的创建与导入 10. __name__ == "__main__" 的作用

例题1:函数的定义与调用

定义函数 area_rectangle(length, width),返回长方形面积。

def area_rectangle(length, width):
    return length * width

print(area_rectangle(5, 3))
print(area_rectangle(8, 2))
15
16

例题2:位置参数

定义函数 calculate(a, b, c),返回 a + b - c。使用位置参数调用。

def calculate(a, b, c):
    return a + b - c

print(calculate(3, 4, 2))
print(calculate(10, 6, 1))
5
15

例题3:关键字参数

仍然使用 calculate(a, b, c),改用关键字参数调用。

def calculate(a, b, c):
    return a + b - c

print(calculate(3, c=2, b=4))
print(calculate(b=7, a=5, c=1))
5
11

例题4:默认值参数

定义函数 power(base, exp=2),默认计算平方。

def power(base, exp=2):
    return base ** exp

print(power(5))      # 默认平方
print(power(2, 5))   # 2 的 5 次方
25
32

例题5:可变长参数 *args

定义函数 my_sum(*args),计算任意多个数字的和。

def my_sum(*args):
    total = 0
    for x in args:
        total += x
    return total

print(my_sum())
# print(my_sum(1, 2, 3))
# print(my_sum(5, 10, 15, 20))
0

例题6:可变长参数 **kwargs

定义函数 show_info(**kwargs),输出传入的键值对。

def show_info(**kwargs):
    # for key, value in kwargs.items():
    #     print(f"{key}: {value}")
    for item in kwargs.items():
        print(item)
    # print(kwargs.items())

show_info(name="Alice", age=20, major="CS")
('name', 'Alice')
('age', 20)
('major', 'CS')

例题7:变量作用域

观察局部变量和全局变量的区别。

x = 100  # 全局变量

def demo_scope():
    x = 50   # 局部变量
    print("函数内部 x =", x)

demo_scope()
print("函数外部 x =", x)
函数内部 x = 50
函数外部 x = 100

例题8:global 的使用

在函数内部修改全局变量。

count = 0

def add_one():
    global count
    count += 1

add_one()
add_one()
print("count =", count)
count = 2

例题9:递归函数

使用递归计算阶乘。

def factorial(n):
    if n == 1 or n == 0:
        return 1
    return n * factorial(n - 1)

print(factorial(0))
print(factorial(8))
1
40320

例题10:lambda 匿名函数

用 lambda 定义一个函数,使输入值加 1。

f = lambda x: x + 1
print(f(3))
print(f(10))
4
11

例题11:lambda + sorted

结合前几章列表知识,用 lambda 指定排序规则。

students = [("Amy", 88), ("Bob", 95), ("Cindy", 90)]
result = sorted(students, key=lambda item: item[1], reverse=True)
print(result)
[('Bob', 95), ('Cindy', 90), ('Amy', 88)]

例题12:模块的创建与导入

在 notebook 中模拟创建一个模块文件,并导入使用。

# module_code = '''
# def add(a, b):
#     return a + b

# def sub(a, b):
#     return a - b
# '''

# with open("mymath_demo.py", "w", encoding="utf-8") as f:
#     f.write(module_code)

import mymath_demo
print(mymath_demo.add(3, 4))
print(mymath_demo.sub(10, 6))
7
4

例题13:from ... import ...

使用另一种导入方式。

from mymath_demo import add, sub
print(add(100, 20))
print(sub(100, 20))
120
80

例题14:name == 'main'

模拟一个带测试入口的模块。

# module_code = '''
# def square(x):
#     return x * x

# if __name__ == "__main__":
#     print("这是模块单独运行时的测试代码")
#     print(square(5))
# '''

# with open("name_demo.py", "w", encoding="utf-8") as f:
#     f.write(module_code)

import name_demo
print(name_demo.square(9))
81

二、20 道结合前几章知识的较难题目(附参考解法)

说明: - 题目重点仍围绕 函数与模块 - 但会结合前几章的字符串、列表、字典、循环、条件判断等知识 - 每题先给题目,再给一份参考解法

1. 统计数字各位和

题目: 编写函数 digit_sum(n),返回整数 n 每一位数字之和,要求负数也能正常处理。

参考解法:

def digit_sum(n):
    n = abs(n)
    total = 0
    while n > 0:
        total += n % 10
        n //= 10
    return total

print(digit_sum(12345))
print(digit_sum(-908))
15
17

2. 判断质数并生成质数列表

题目: 编写函数 is_prime(n) 判断 n 是否为质数;再写函数 primes_upto(n) 返回 1~n 的所有质数。

参考解法:

def is_prime(n):
    if n < 2:
        return False
    i = 2
    while i * i <= n:
        if n % i == 0:
            return False
        i += 1
    return True

def primes_upto(n):
    result = []
    for x in range(2, n + 1):
        if is_prime(x):
            result.append(x)
    return result

print(is_prime(29))
print(primes_upto(30))
True
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

3. 统计列表中不同数据类型个数

题目: 编写函数 count_types(data),统计列表中整数、浮点数、字符串、布尔值各有多少个。

参考解法:

def count_types(data):
    result = {"int": 0, "float": 0, "str": 0, "bool": 0}
    for item in data:
        if type(item) is bool:
            result["bool"] += 1
        elif type(item) is int:
            result["int"] += 1
        elif type(item) is float:
            result["float"] += 1
        elif type(item) is str:
            result["str"] += 1
    return result

print(count_types([1, 2.5, "hi", True, False, "ok", 9]))
{'int': 2, 'float': 1, 'str': 2, 'bool': 2}

4. 反转句子中的单词顺序

题目: 编写函数 reverse_words(s),将一句英文中的单词顺序反转。

参考解法:

def reverse_words(s):
    words = s.split()
    words.reverse()
    return " ".join(words)

print(reverse_words("I love python very much"))
much very python love I

5. 不把数字转字符串,判断回文数

题目: 编写函数 palindrome_number(n),判断一个整数是否为回文数,不能直接把数字转成字符串。

参考解法:

def palindrome_number(n):
    if n < 0:
        return False
    original = n
    rev = 0
    while n > 0:
        rev = rev * 10 + n % 10
        n //= 10
    return original == rev

print(palindrome_number(121))
print(palindrome_number(123))
True
False

6. 找列表中的第二大值

题目: 编写函数 find_second_max(nums),返回列表中的第二大值;若不存在则返回 None

参考解法:

def find_second_max(nums):
    unique = []
    for x in nums:
        if x not in unique:
            unique.append(x)
    if len(unique) < 2:
        return None
    unique.sort(reverse=True)
    return unique[1]

print(find_second_max([5, 1, 9, 9, 7, 5]))
print(find_second_max([3]))
7
None

7. 去重但保持原顺序

题目: 编写函数 remove_duplicates_keep_order(nums),删除列表重复元素,但保持原顺序不变。

参考解法:

def remove_duplicates_keep_order(nums):
    seen = set()
    result = []
    for x in nums:
        if x not in seen:
            seen.add(x)
            result.append(x)
    return result

print(remove_duplicates_keep_order([1, 2, 2, 3, 1, 4, 3]))
[1, 2, 3, 4]

8. 统计字符频率

题目: 编写函数 char_frequency(s),返回字符串中每个字符出现次数组成的字典,忽略空格与大小写差异。

参考解法:

def char_frequency(s):
    freq = {}
    for ch in s.lower():
        if ch == " ":
            continue
        freq[ch] = freq.get(ch, 0) + 1
    return freq

print(char_frequency("Hello World"))
{'h': 1, 'e': 1, 'l': 3, 'o': 2, 'w': 1, 'r': 1, 'd': 1}

9. 密码合法性检查

题目: 编写函数 password_check(pwd),长度至少 8,且至少包含大写字母、小写字母和数字。

参考解法:

def password_check(pwd):
    if len(pwd) < 8:
        return False
    has_upper = False
    has_lower = False
    has_digit = False
    for ch in pwd:
        if ch.isupper():
            has_upper = True
        elif ch.islower():
            has_lower = True
        elif ch.isdigit():
            has_digit = True
    return has_upper and has_lower and has_digit

print(password_check("Abc12345"))
print(password_check("abc12345"))
True
False

10. 判断三角形类型

题目: 编写函数 triangle_type(a, b, c),判断三边能否构成三角形,并返回类型。

参考解法:

def triangle_type(a, b, c):
    if a + b <= c or a + c <= b or b + c <= a:
        return "非法"
    if a == b == c:
        return "等边三角形"
    if a == b or a == c or b == c:
        return "等腰三角形"
    return "普通三角形"

print(triangle_type(3, 3, 3))
print(triangle_type(3, 4, 5))
print(triangle_type(1, 2, 3))
等边三角形
普通三角形
非法

11. 最大公约数与最小公倍数

题目: 编写函数 gcd(a, b)lcm(a, b)

参考解法:

def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return abs(a)

def lcm(a, b):
    return abs(a * b) // gcd(a, b)

print(gcd(24, 18))
print(lcm(24, 18))
6
72

12. 找完全数

题目: 编写函数 perfect_numbers(n),找出 1~n 中所有完全数。

参考解法:

def is_perfect(x):
    if x < 2:
        return False
    total = 1
    i = 2
    while i * i <= x:
        if x % i == 0:
            total += i
            if i != x // i:
                total += x // i
        i += 1
    return total == x

def perfect_numbers(n):
    result = []
    for x in range(2, n + 1):
        if is_perfect(x):
            result.append(x)
    return result

print(perfect_numbers(1000))
[6, 28, 496]

13. 成绩报表

题目: 编写函数 score_report(scores),输入一个分数字典,输出最高分、最低分、平均分和不及格人数。

参考解法:

def score_report(scores):
    values = list(scores.values())
    return {
        "最高分": max(values),
        "最低分": min(values),
        "平均分": sum(values) / len(values),
        "不及格人数": sum(1 for x in values if x < 60)
    }

scores = {"Amy": 88, "Bob": 59, "Cindy": 95, "David": 40}
print(score_report(scores))
{'最高分': 95, '最低分': 40, '平均分': 70.5, '不及格人数': 2}

14. 合并两个有序列表

题目: 编写函数 merge_sorted(a, b),把两个升序列表合并成一个新的升序列表,不能直接调用 sort()

参考解法:

def merge_sorted(a, b):
    i = 0
    j = 0
    result = []
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            result.append(a[i])
            i += 1
        else:
            result.append(b[j])
            j += 1
    result.extend(a[i:])
    result.extend(b[j:])
    return result

print(merge_sorted([1, 3, 5, 8], [2, 4, 6, 7, 9]))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

15. 十进制转二进制

题目: 编写函数 to_binary(n),把十进制非负整数转换为二进制字符串,不能直接调用 bin()

参考解法:

def to_binary(n):
    if n == 0:
        return "0"
    digits = []
    while n > 0:
        digits.append(str(n % 2))
        n //= 2
    digits.reverse()
    return "".join(digits)

print(to_binary(13))
print(to_binary(255))
1101
11111111

16. 二进制转十进制

题目: 编写函数 from_binary(bstr),把二进制字符串转换成十进制整数。

参考解法:

def from_binary(bstr):
    value = 0
    for ch in bstr:
        value = value * 2 + int(ch)
    return value

print(from_binary("1101"))
print(from_binary("11111111"))
13
255

17. 支持重叠统计的子串计数

题目: 编写函数 count_substring(text, sub),统计子串出现次数,要求支持重叠统计。

参考解法:

def count_substring(text, sub):
    count = 0
    for i in range(len(text) - len(sub) + 1):
        if text[i:i+len(sub)] == sub:
            count += 1
    return count

print(count_substring("aaaa", "aa"))
print(count_substring("abababa", "aba"))
3
3

18. 把 0 移动到末尾

题目: 编写函数 move_zeros(nums),将列表中所有 0 移到末尾,同时保持非 0 元素相对顺序不变。

参考解法:

def move_zeros(nums):
    non_zero = []
    zero_count = 0
    for x in nums:
        if x == 0:
            zero_count += 1
        else:
            non_zero.append(x)
    return non_zero + [0] * zero_count

print(move_zeros([0, 1, 0, 3, 12, 0, 5]))
[1, 3, 12, 5, 0, 0, 0]

19. 返回分数前 k 名学生

题目: 编写函数 students_top_k(records, k=3),返回分数前 k 名学生。

参考解法:

def students_top_k(records, k=3):
    return sorted(records, key=lambda item: item[1], reverse=True)[:k]

records = [("Amy", 88), ("Bob", 95), ("Cindy", 90), ("David", 78)]
print(students_top_k(records, 2))
[('Bob', 95), ('Cindy', 90)]

20. 菜单式计算器

题目: 编写一个菜单式计算器程序:循环显示菜单,分别调用加减乘除等函数。下面给出一个简化可运行参考版本。

参考解法:

def add(a, b):
    return a + b

def sub(a, b):
    return a - b

def mul(a, b):
    return a * b

def div(a, b):
    return "除数不能为 0" if b == 0 else a / b

def menu_demo(operations):
    for op, a, b in operations:
        if op == "+":
            print(a, "+", b, "=", add(a, b))
        elif op == "-":
            print(a, "-", b, "=", sub(a, b))
        elif op == "*":
            print(a, "*", b, "=", mul(a, b))
        elif op == "/":
            print(a, "/", b, "=", div(a, b))

# 用预设数据模拟菜单选择结果
menu_demo([
    ("+", 3, 5),
    ("-", 10, 4),
    ("*", 6, 7),
    ("/", 8, 2),
    ("/", 8, 0),
])
3 + 5 = 8
10 - 4 = 6
6 * 7 = 42
8 / 2 = 4.0
8 / 0 = 除数不能为 0