
一、流程控制1条件分支1.if / elif / elsex 10 if x 20: print(A) elif x 5: print(B) else: print(C)2.三元表达式result big if x 5 else small2循环结构1.for 循环 —— 专用于遍历可迭代对象for i in [1, 2, 3]: # 列表 print(i) for ch in hello: # 字符串 print(ch) # range(start, stop, step) 生成整数序列 for i in range(5): # 0 1 2 3 4 print(i) for i in range(2, 6): # 2 3 4 5 print(i) for i in range(10, 0, -2): # 10 8 6 4 2 print(i) for idx, val in enumerate([a, b, c]): print(idx, val) # 0 a, 1 b, 2 c2.while循环count 0 while count 5: print(count) count 13.break / continue / elsebreak跳出整个循环continue跳过本次循环剩余代码进入下一次迭代else子句如果循环正常结束没有被break中断会执行else块for i in range(5): if i 3: break else: print(没 break) # 这里不会执行因为 break 了3流程控制练习题题目1条件分支 —— 成绩等级转换从键盘输入一个分数0–100 的整数根据规则打印等级90 及以上A80–89B70–79C60–69D60 以下F输入不是数字或越界则提示错误。try: score int(input(请输入一个分数)) if score 0 and score 100: if score 90: print(分数等级为A) elif score 80: print(分数等级为B) elif score 70: print(分数等级为C) elif score 60: print(分数等级为D) else: print(分数等级为F) else: print(分数不在0~100范围内) except ValueError: print(非数字输入错误)题目2for 循环 —— 统计与列表生成给定列表numbers [3, 7, 12, 5, 8, 11, 6]请用for循环计算所有元素的和并找出最大值、最小值不要用内置sum/max/min自己写循环生成一个新列表包含所有偶数的平方用列表推导式numbers [3, 7, 12, 5, 8, 11, 6] numbers_sum 0 numbers_max -9999999 numbers_min 9999999 for x in numbers: numbers_sum x numbers_max x if numbers_max x else numbers_max numbers_min x if numbers_min x else numbers_min numbers_square [y*y for y in numbers if y%2 0] print(f元素总和为{numbers_sum},最大值为{numbers_max},最小值为{numbers_min},偶数平方列表为{numbers_square})运行结果元素总和为52,最大值为12,最小值为3,偶数平方列表为[144, 64, 36]题目3嵌套循环与 break/else —— 查找质数打印 2 到 20 之间的所有质数。要求外层循环遍历数字内层循环检查是否存在因子正确使用for-else结构在未找到因子时打印该数for x in range(2,21): for n in range(2,x): if x%n 0: break else: print(x, end )运行结果2 3 5 7 11 13 17 19题目4while 循环 —— 猜数字游戏程序随机生成一个 1 到 100 之间的整数用户每次输入猜测给出“大了”、“小了”提示直到猜对为止并统计猜测次数。要求用while Truebreak实现。num random.randint(1,100) cs 0 while True: try: x int(input(请输入一个1~100之间的整数包括1和100)) cs 1 if x num: print(大了) elif x num: print(小了) else: print(f恭喜你猜中了幸运数为{num}) break except ValueError: print(您输入的不是整数请重新输入)运行结果请输入一个1~100之间的整数包括1和10050 小了 请输入一个1~100之间的整数包括1和10075 大了 请输入一个1~100之间的整数包括1和10062 小了 请输入一个1~100之间的整数包括1和10069 小了 请输入一个1~100之间的整数包括1和10072 大了 请输入一个1~100之间的整数包括1和10070 恭喜你猜中了幸运数为70题目5综合 —— 菜单驱动程序骨架实现一个简单的菜单循环1. Say Hello 2. Count numbers 3. Exit选择 1 时打印 Hello!选择 2 时让用户输入一个正整数 N然后用for打印 1 到 N选择 3 退出其他输入提示无效。要求使用while循环保持菜单运行直到退出。while True: print(以下为选项菜单请输入数字1、2或3) print(1. Say Hello) print(2. Count numbers) print(3. Exit) try: num int(input(请输入)) if num 1: print(Hello!) elif num 2: while True: try: N int(input(请输入一个正整数N)) for x in range(1,N): print(x,end ) else: print(N) break except ValueError: print(输入的N不是数字请重新输入) elif num 3: print(退出菜单) break else: print(输入的不是数值1、2或3请重新输入) except ValueError: print(您输入菜单选项的不是数字请重新输入)运行结果以下为选项菜单请输入数字1、2或3 1. Say Hello 2. Count numbers 3. Exit 请输入a 您输入菜单选项的不是数字请重新输入 以下为选项菜单请输入数字1、2或3 1. Say Hello 2. Count numbers 3. Exit 请输入0 输入的不是数值1、2或3请重新输入 以下为选项菜单请输入数字1、2或3 1. Say Hello 2. Count numbers 3. Exit 请输入1 Hello! 以下为选项菜单请输入数字1、2或3 1. Say Hello 2. Count numbers 3. Exit 请输入2 请输入一个正整数N5 1 2 3 4 5 以下为选项菜单请输入数字1、2或3 1. Say Hello 2. Count numbers 3. Exit 请输入3 退出菜单二、函数1基本定义 —— 没有类型声明全靠defdef add(a, b): return a b2参数传递 —— 记住两句口诀可变对象list/dict/set在函数内修改会影响到外部。不可变对象int/str/tuple不会影响外部因为“修改”实际上是重新绑定。def try_change(num, lst): num 999 # 新标签不影响外部 lst.append(4) # 直接修改原对象外部可见 a 10 b [1,2,3] try_change(a, b) print(a, b) # 10, [1,2,3,4]3参数形态 —— 灵活多变# 默认参数默认值只初始化一次不要用可变对象当默认值 def greet(name, msgHello): return f{msg}, {name} # 位置参数、关键字参数 def config(host, port80, timeout30): pass config(1.2.3.4, timeout10) # 关键字传参 config(port443, hostlocalhost) # 打乱顺序也可以 # 可变参数*args—— 接收任意数量位置参数打包成元组 def sum_all(*numbers): total 0 for n in numbers: total n return total print(sum_all(1, 2, 3, 4)) # 10 # 关键字可变参数**kwargs—— 接收任意数量关键字参数打包成字典 def print_info(**kwargs): for key, value in kwargs.items(): print(f{key}: {value}) print_info(nameTom, age20) # 解包实参 nums [1, 2, 3] print(sum_all(*nums)) # 列表解开传给 *args info {name: Tom, age: 20} print_info(**info) # 字典解开传给 **kwargs4返回值 —— 天生支持“多返回值”def min_max(a, b): if a b: return b, a # 返回的是元组 (b, a) return a, b small, big min_max(5, 3) # 自动解包5lambda 表达式 —— 匿名函数add lambda x, y: x y print(add(2, 3)) # 5 # 常用于排序、filter、map pairs [(1, one), (3, three), (2, two)] pairs.sort(keylambda p: p[0]) # 按第一个元素排序6装饰器 —— 给函数“穿衣服”def my_decorator(func): def wrapper(): print(Before) func() print(After) return wrapper my_decorator def say_hi(): print(Hi!) say_hi() # 输出Before / Hi! / After7作用域规则 —— LEGB查找顺序Local →Enclosing function →Global →Built-in在函数内要修改全局变量需要global声明。闭包内修改外层变量需要nonlocal。8函数练习题题目1基础定义与返回值写一个函数rectangle_info(length, width)返回一个元组包含矩形的面积和周长。调用函数并解包打印结果。def rectangle_info(length, width): return length * width, (length width) * 2 s, c rectangle_info(2, 3) print(f边长为23的举行的面积为{s}周长为{c})运行结果边长为23的举行的面积为6周长为10题目2列表参数与原地修改写一个函数remove_duplicates(lst)接受一个列表原地移除重复元素保持原有顺序不返回新列表。思考如果要求生成一个新列表并返回该怎么做def remove_duplicates(lst): i 0 while i len(lst): j i 1 while j len(lst): if(lst[j] lst[i]): lst.pop(j) else: j 1 i 1 li [1, 3, 3, 5, 7, 3, 5, 9] remove_duplicates(li) print(f去重后的列表为{li}) # 思考如果要求生成一个新列表并返回该怎么做 def remove_duplicates_new_list(lst): lst_tmp [] i 0 while i len(lst): if lst[i] not in lst_tmp: lst_tmp.append(lst[i]) i 1 return lst_tmp li_old [1, 3, 3, 5, 7, 3, 5, 9] li_new remove_duplicates_new_list(li_old) print(f老列表为{li_old},新列表为{li_new})运行结果去重后的列表为[1, 3, 5, 7, 9] 老列表为[1, 3, 3, 5, 7, 3, 5, 9],新列表为[1, 3, 5, 7, 9]题目3递归 —— 斐波那契与搜索1用递归实现斐波那契数列fib(n)返回第 n 项从 0 开始fib(0)0, fib(1)1。2写一个递归函数binary_search(arr, target, low, high)在有序列表中查找目标找到返回索引否则返回 -1。def fib(n): if n 0: return 0 elif n 1: return 1 else: return fib(n - 2) fib(n - 1) print(f斐波那契的第8项为{fib(8)}) # 0 1 1 2 3 5 8 13 21 def binary_search(arr, target, low, high): mid (low high) // 2 if low high: return -1 elif target arr[mid]: return mid elif target arr[mid]: return binary_search(arr, target, low, mid - 1) elif target arr[mid]: return binary_search(arr, target, mid 1, high) sorted_list [2, 5, 8, 12, 16, 23, 38] print(f16对应的项为第{binary_search(sorted_list, 16, 0, len(sorted_list)-1)}项) # 4运行结果斐波那契的第8项为21 16对应的项为第4项题目4可变参数与关键字参数写一个函数create_profile(name, **details)要求name是必须的位置参数details接收任意关键字参数如age25, cityNY返回一个字典包含 name 和所有 details调用时用关键字传入任意额外信息def create_profile(name, **details): info {} info[姓名] name info.update(details) return info xiaoming_info create_profile(小明,年龄 25, 性别 男, 城市 杭州) print(f小明的相关信息{xiaoming_info})运行结果小明的相关信息{姓名: 小明, 年龄: 25, 性别: 男, 城市: 杭州}题目5lambda 与高阶函数给定列表students [(Tom, 85), (Jerry, 92), (Spike, 78)]用sorted()按分数降序排列用lambda指定 key用filter()结合lambda筛选分数 ≥ 80 的学生用map()结合lambda将所有姓名转为大写students [(Tom, 85), (Jerry, 92), (Spike, 78)] students_sort sorted(students, key lambda p:p[1], reverseTrue) print(f分数降序后的成绩列表为{students_sort}) students_more80 list(filter(lambda p:p[1] 80,students)) print(f分数80的成绩列表为{students_more80}) students_upper list(map(lambda p:p[0].upper(),students)) print(f姓名转成大写后的列表为{students_upper})运行结果分数降序后的成绩列表为[(Jerry, 92), (Tom, 85), (Spike, 78)] 分数80的成绩列表为[(Tom, 85), (Jerry, 92)] 姓名转成大写后的列表为[TOM, JERRY, SPIKE]三、类和继承1定义一个类 —— 没有头文件没有类型声明class Dog: # 类属性所有实例共享类似静态成员 species Canis familiaris # 构造方法初始化实例第一个参数固定是 self def __init__(self, name, age): self.name name # 实例属性 self.age age # 实例方法 def bark(self): print(f{self.name} says woof!)2创建对象、访问属性my_dog Dog(Fido, 3) print(my_dog.name) # Fido my_dog.bark() # Fido says woof! my_dog.color brown # 可以随意在运行时添加属性3继承 —— 重用与多态class Beagle(Dog): # 继承自 Dog def bark(self): # 重写方法 print(f{self.name} howls!) class Cat: def __init__(self, name): self.name name def speak(self): print(f{self.name} meows)class Beagle(Dog): def __init__(self, name, age, trick): super().__init__(name, age) # 调用父类 __init__ self.trick trick4特殊方法 —— “魔术方法”以双下划线包裹定制类的行为 __str__(self)被 print() 或 str() 调用返回用户友好的字符串。 __repr__(self)调试用的“官方”表示通常返回能重建对象的字符串。 __eq__(self, other)定义 行为。 __len__、__getitem__ 等让自定义类像内置容器。5类与继承练习题题目1定义一个矩形类创建一个Rectangle类初始化传入width和height提供area()方法返回面积提供perimeter()方法返回周长重写__str__方法返回形如Rectangle(width, height)的字符串class Rectangle: def __init__(self, width, height): self.width width self.height height def __str__(self): return fRectangle({self.width}, {self.height}) def area(self): return self.width * self.height def perimeter(self): return (self.width self.height) * 2 rect Rectangle(2, 3) print(rect) print(f边长为2和3的长方形面积为{rect.area()},周长为{rect.perimeter()})运行结果Rectangle(2, 3) 边长为2和3的长方形面积为6,周长为10题目2继承与方法重写设计一个类层次Vehicle基类初始化brand,model提供get_description()返回brand modelCar子类增加num_doors属性重写get_description()返回brand model (Car, num_doors doors)并在其中调用父类的get_description()Motorcycle子类增加has_sidecar布尔属性重写get_description()展示是否有侧斗class Vehicle: def __init__(self, brand, model): self.brand brand self.model model def get_description(self): return f{self.brand},{self.model} class Car(Vehicle): def __init__(self, brand, model, num_doors): super().__init__(brand, model) self.num_doors num_doors def get_description(self): base super().get_description() return fbase (Car, {self.num_doors} doors) class Motorcycle(Vehicle): def __init__(self, brand, model, has_sidecar: bool): super().__init__(brand,model) self.has_sidecar has_sidecar def get_description(self): base super().get_description() iscedou 有侧斗 if self.has_sidecar else 没有侧斗 return base iscedou # 测试 car Car(Toyota, Camry, 4) moto Motorcycle(Harley, Sportster, False) print(car.get_description()) print(moto.get_description())运行结果base (Car, 4 doors) Harley,Sportster 没有侧斗题目3多态 —— 统一接口在题目2类的基础上写一个函数describe_vehicles(vehicles)接收一个车辆列表对每个车辆调用get_description()并打印。传入Car和Motorcycle的实例验证多态。def describe_vehicles(vehicles): for v in vehicles: print(v.get_description()) fleet [ Car(Honda, Civic, 2), Motorcycle(Yamaha, MT-07, False), Car(Ford, Fusion, 4) ] describe_vehicles(fleet)运行结果base (Car, 2 doors) Yamaha,MT-07 没有侧斗 base (Car, 4 doors)题目4魔术方法 —— 自定义比较创建一个Student类有name和score属性。重写__eq__使得分数相等即认为学生相等重写__lt__使得按分数比较低于用sorted()对一个学生列表排序并打印结果重写__repr__为Student(name, score)方便调试class Student: def __init__(self, name, score): self.name name self.score score def __eq__(self, other): if isinstance(other, Student): return self.score other.score return NotImplemented def __lt__(self, other): if isinstance(other, Student): return self.score other.score return NotImplemented def __repr__(self): return fStudent({self.name}, {self.score}) # 测试 students [ Student(Tom, 85), Student(Jerry, 92), Student(Spike, 78) ] print(sorted(students)) # [Student(Spike, 78), Student(Tom, 85), Student(Jerry, 92)] print(Student(A, 85) Student(B, 85))运行结果[Student(Spike, 78), Student(Tom, 85), Student(Jerry, 92)] True题目5简单继承与属性 —— 文件系统模拟设计一个FileSystemNode类有name属性一个File子类额外有size属性一个Directory子类额外有children列表属性并提供add_child(node)方法。给每个类写一个__str__方法展示名称和如果是文件大小如果是目录则展示子节点数量。写一个测试创建一个根目录其中包含两个文件和另一个子目录再打印结构。class FileSystemNode: def __init__(self, name): self.name name class File(FileSystemNode): def __init__(self, name, size): super().__init__(name) self.size size def __str__(self): return f{self.name},{self.size} bytes class Directory(FileSystemNode): def __init__(self, name): super().__init__(name) self.children [] def __str__(self): return f{self.name},节点数量为{len(self.children)} def add_child(self, node): self.children.append(node) # 测试 root Directory(root) root.add_child(File(file1, 1024)) root.add_child(File(file2, 4096)) root.add_child(Directory(child_directory)) print(root) for child in root.children: print(child)运行结果root,节点数量为3 file1,1024 bytes file2,4096 bytes child_directory,节点数量为0四、文件读写1打开文件 ——open()f open(test.txt, r, encodingutf-8) data f.read() f.close() # 必须关闭常用模式模式含义r只读文件必须存在w只写清空已有内容文件不存在则创建a追加写r读写b二进制模式如rb,wb读写图片、视频等2更优雅的方式 ——with语句推荐with open(test.txt, r, encodingutf-8) as f: content f.read() # 这里 f 已经自动关闭3读取方法# 1. 一次性读取整个文件小心大文件 text f.read() # 2. 读取一行 line f.readline() # 3. 读取所有行返回列表 lines f.readlines() # 4. 最常用直接迭代文件对象惰性读取内存友好 for line in f: print(line.strip())4写入方法with open(output.txt, w, encodingutf-8) as f: f.write(Hello\n) # 不会自动加换行 f.writelines([a\n, b\n]) # 写入多个字符串5二进制读写 —— 处理图片、音频等with open(source.jpg, rb) as src: data src.read() # 返回 bytes 对象不是 str with open(dest.jpg, wb) as dst: dst.write(data)6路径与文件系统推荐用pathlib模块操作路径Python 3.6比手动拼字符串更干净。from pathlib import Path path Path(data) / test.txt # 跨平台拼接 text path.read_text(encodingutf-8)7文件读写练习题题目1实现简易wc—— 统计文件行数、单词数、字符数新建一个文本文件sample.txt内容随意英文。编写程序读取该文件输出行数、单词数以空白字符分割、字符数含空格和换行。def wc(filename): hs 0 dcs 0 zfs 0 with open(filename, r, encoding utf-8) as f: for line in f: hs 1 dcs len(line.split( )) zfs len(line) return hs, dcs, zfs hs, dcs, zfs wc(sample.txt) print(f行数{hs},单词数{dcs},字符数:{zfs})文本内容My favorite day at I can draw colorful运行结果行数2,单词数8,字符数:38题目2读取 CSV 格式文件并处理假设有一个scores.csv文件内容如下无标题行Alice,85 Bob,92 Charlie,78请读取该文件计算并打印平均分保留一位小数同时用列表推导式生成一个新列表包含分数大于 80 的学生姓名。sum 0 rs 0 lst1 [] with open(scores.csv, r, encodingutf-8) as f: for line in f: rs 1 sum int(line.split(,)[1]) line line.rstrip(\n) lst1.append((line.split(,)[0], line.split(,)[1])) avg sum / rs lst2 [x[0] for x in lst1 if int(x[1]) 80] print(favg {avg:.1f}) print(lst1) print(f分数大于80的学生有{lst2})运行结果avg 85.0 [(Alice, 85), (Bob, 92), (Charlie, 78)] 分数大于80的学生有[Alice, Bob]题目3写文件 —— 生成乘法表编写程序将 9×9 乘法表输出到文件multiplication.txt格式如下1×11 1×22 2×24 ...要求用with和write完成每行末尾有换行。with open(multiplication.txt, w, encodingutf-8) as f: for i in range(1, 10): for j in range(1, i1): f.write(f{j}*{i}{j*i:2} ) f.write(\n)题目4文件复制 —— 二进制大文件分块读写实现一个函数copy_file(source, dest, buffer_size8192)将源文件复制到目标文件支持任意类型文本、图片、视频避免一次性读取大文件耗尽内存。def copy_file(source, dest, buffer_size8192): with open(source, rb) as rf, open(dest, wb) as wf: while True: b rf.read() if not b: break wf.write(b) copy_file(QQ20260624-175510.png, QQ20260624-175511.png)题目5配置文件解析 —— 异常处理与字典给定配置文件config.txt每行格式为keyvalue忽略空行和以#开头的注释行。请编写函数parse_config(filename)返回一个字典键值都是字符串。示例config.txt# Database settings hostlocalhost port5432 useradmin要求使用with和逐行迭代捕获文件不存在的异常打印错误并返回空字典def parse_config(filename): dct {} try: with open(filename, r, encodingutf-8) as f: for line in f: if line[0] ! #: line line.rstrip(\n) dct[line.split()[0]] line.split()[1] except FileNotFoundError: print(文件不存在) return dct print(parse_config(config.txt))运行结果{host: localhost, port: 5432, user: admin}五、异常处理1基本结构 ——try/except/else/finallytry: result 10 / 0 except ZeroDivisionError: print(不能除以零) else: print(没有异常时执行) finally: print(不管有没有异常最后都执行)except捕获指定异常类型不写类型会捕获所有不推荐。else子句只在try块没有发生异常时执行常用于“成功后的操作”。finally子句无论如何都执行适合释放资源但文件用with更好。2常见异常类型内置异常类触发场景类似 C 中的情况ValueError类型对值不对如int(abc)sscanf失败TypeError操作类型不支持如a 1类型不匹配IndexError列表索引越界数组越界KeyError字典键不存在访问不存在的变量FileNotFoundError文件不存在fopen返回 NULLZeroDivisionError除以零SIGFPEAttributeError对象没有该属性/方法访问不存在的成员NameError变量未定义未声明捕获多个异常try: x int(input(Enter: )) except (ValueError, TypeError): print(输入错误)获取异常对象try: x 1 / 0 except ZeroDivisionError as e: print(f错误: {e}) # 错误: division by zero3主动抛出异常 ——raisedef set_age(age): if age 0: raise ValueError(年龄不能为负)4自定义异常class MyError(Exception): pass raise MyError(something happened)5断言 ——assertx -5 assert x 0, x 不能为负 # 失败会抛 AssertionError6异常处理练习题题目1输入整数验证编写一个函数get_positive_int(prompt)反复提示用户输入直到用户输入一个有效的正整数。使用异常处理应对非法输入如字母、负数、小数、0。返回该正整数。def get_positive_int(prompt): while True: try: num int(input(prompt)) if num 0: raise ValueError except ValueError: print(您输入的不是整数请重新输入) else: return num print(f您输入的正整数为:{get_positive_int(请输入一个正整数:)})运行结果请输入一个正整数:a 您输入的不是整数请重新输入 请输入一个正整数:-1 您输入的不是整数请重新输入 请输入一个正整数:0 您输入的不是整数请重新输入 请输入一个正整数:1.1 您输入的不是整数请重新输入 请输入一个正整数:3 您输入的正整数为:3题目2安全的字典取值与计算写一个函数safe_divide_from_dict(data, key_a, key_b)接收字典data和两个键。尝试取出两个键对应的值将其转为float后计算除法a / b。如果键不存在捕获异常并提示哪个键缺失。如果值不能转为数字提示格式错误。如果除数为零提示不能除以零。如果成功返回计算结果保留两位小数否则返回None。def safe_divide_from_dict(data, key_a, key_b): try: value_a float(data[key_a]) value_b float(data[key_b]) result value_a /value_b return round(result, 2) except KeyError as e: print(f键{e}不存在) return None except ValueError as e: print(f输入类型不正确,{e}) return None except ZeroDivisionError as e: print(f除数不能为0,{e}) return None # 测试 d {x: 10, y: 0, z: hello} print(safe_divide_from_dict(d, x, y)) # 除数不能为零 - None print(safe_divide_from_dict(d, x, w)) # 键 w 不存在 - None print(safe_divide_from_dict(d, x, z)) # 值无法转换 - None print(safe_divide_from_dict(d, x, x)) # 10 / 10 1.0运行结果除数不能为0,float division by zero None 键w不存在 None 输入类型不正确,could not convert string to float: hello None 1.0题目3文件处理中的 finally/else编写一个函数count_lines(filename)统计指定文本文件的行数并返回行数。要求用try/except/else/finally完整结构try中打开文件并计数。捕获FileNotFoundError打印 “文件不存在” 并返回 -1。else中打印 “文件读取成功”。finally中打印 “操作结束”。def count_lines(filename): try: hs 0 with open(filename, r, encodingutf-8) as f: for line in f: hs 1 except FileNotFoundError: print(f文件{filename}不存在) return -1; else: print(文件读取成功) return hs finally: print(操作结束) hs count_lines(sample.txt) if hs ! -1: print(f文件sample.txt有{hs}行) hs count_lines(sample2.txt) if hs ! -1: print(f文件sample2.txt有{hs}行)运行结果文件读取成功 操作结束 文件sample.txt有2行 文件sample2.txt不存在 操作结束题目4自定义异常与 raise定义一个异常类NegativeAgeError继承自ValueError。编写一个函数create_person(name, age)如果age为负数抛出NegativeAgeError附带提示信息。如果name为空字符串抛出ValueError。正常时返回一个包含姓名和年龄的字典。编写测试代码分别传入正确和错误参数捕获并打印异常信息。class NegativeAgeError(ValueError): 年龄为负数的异常 pass def create_person(name, age): try: if age 0: raise NegativeAgeError if name : raise ValueError return {name:name, age:age} except NegativeAgeError: print(年龄错误年龄为负数) return None except ValueError: print(姓名错误姓名为空) return None #测试 test_cases [(Alice, 30), (, 25), (Bob, -5)] for name, age in test_cases: person create_person(name, age) if person ! None: print(f创建成功: {person})运行结果创建成功: {name: Alice, age: 30} 姓名错误姓名为空 年龄错误年龄为负数题目5异常链与转换在题目2的基础上改进safe_divide_from_dict如果除法时发生ZeroDivisionError将其转换为一个自定义的CalculationError异常继承自Exception并保留原始异常信息。使用raise ... from ...链式抛出。class CalculationError(Exception): pass def safe_divide_from_dict_v2(data, key_a, key_b): try: value_a float(data[key_a]) value_b float(data[key_b]) result value_a /value_b return round(result, 2) except KeyError as e: print(f键{e}不存在) return None except ValueError as e: print(f输入类型不正确,{e}) return None except ZeroDivisionError as e: raise CalculationError(除数零导致计算错误) from e # 测试 try: d {x: 10, y: 0} print(safe_divide_from_dict_v2(d, x, y)) except CalculationError as e: print(f捕获自定义异常: {e}) print(f原始异常: {e.__cause__}) # 输出: # 捕获自定义异常: 除以零导致计算错误 # 原始异常:float division by zero运行结果捕获自定义异常: 除数零导致计算错误 原始异常: float division by zero