Python中match语句内变量的存储位置及跨case访问问题
问题解答
1. todos变量的存储位置
Python没有块级作用域(像if、for、match这类代码块不会创建独立的作用域),你在case 'add'分支里定义的todos,属于全局作用域(因为这段代码没有包裹在函数或类中,直接在模块级别执行)。一旦case 'add'的代码执行过,这个变量就会被存在全局命名空间里,直到程序结束。
2. 不同case分支能访问该变量的原因
所有match的case分支都共享同一个外层作用域(这里就是全局作用域),只要todos变量已经被定义过(也就是case 'add'的代码执行过),后续的show、edit、complete分支就能直接访问到这个变量——因为它们不在独立的作用域里,能直接读取外层作用域的变量。
为什么首次执行show会报错?
当你第一次直接选show时,case 'add'的代码从来没运行过,todos变量根本没被定义过,Python在当前作用域里找不到这个变量,就会抛出NameError: name 'todos' is not defined。而先执行add分支的话,todos已经被创建并赋值了,后续分支自然能正常访问。
修复建议
要避免首次执行show/edit/complete分支报错,最好在程序开头就初始化todos变量,不管有没有执行add操作,先从文件读取(文件不存在就初始化为空列表):
# 初始化todos变量,提前处理文件不存在的情况 try: with open('todos.txt', 'r') as file: todos = file.readlines() except FileNotFoundError: todos = [] while True: user_action = input("Type add, show, edit, complete or exit: ").strip().lower() match user_action: case 'add': todo = input("Enter a todo: ") + "\n" todos.append(todo) with open('todos.txt', 'w') as file: file.writelines(todos) case 'show' | 'display': for index, item in enumerate(todos): # 去掉换行符避免重复换行 print(f"{index+1}-{item.strip()}") case 'edit': try: number = int(input("Number of the todo to edit: ")) - 1 new_todo = input("Enter new todo: ").capitalize() + "\n" todos[number] = new_todo with open('todos.txt', 'w') as file: file.writelines(todos) except (ValueError, IndexError): print("Invalid todo number!") case 'complete': try: number = int(input("Number of the todo to complete: ")) - 1 todos.pop(number) with open('todos.txt', 'w') as file: file.writelines(todos) except (ValueError, IndexError): print("Invalid todo number!") case 'exit': break case _: print("Hey, you entered an unknown command") print("Bye!")
(顺便优化了文件操作,用with语句自动关闭文件,还加了异常处理避免输入非数字或无效索引的报错)
内容的提问来源于stack exchange,提问作者pythonPlant
相关产品推荐
相关产品推荐

