第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。使用位置参数调用。
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),默认计算平方。
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 = 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。
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 ...
使用另一种导入方式。
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