Ray*_*ger 39 python syntax-error switch-statement python-3.10 structural-pattern-matching
为什么这段代码会失败:
OKAY = 200
NOT_FOUND = 404
INTERNAL_SERVER_ERROR = 500
match status:
case OKAY:
print('It worked')
case NOT_FOUND:
print('Unknown')
case INTERNAL_SERVER_ERROR:
print('Out of service')
case _:
print('Unknown code')
Run Code Online (Sandbox Code Playgroud)
它会生成以下错误消息:
File "/Users/development/Documents/handler.py", line 66
case OKAY:
^^^^
SyntaxError: name capture 'OKAY' makes remaining patterns unreachable
Run Code Online (Sandbox Code Playgroud)
该错误消息意味着什么以及如何修复代码以使其正常工作?
Ray*_*ger 42
case子句中的变量名称被视为名称捕获模式。
它始终匹配并尝试对变量名称进行赋值。几乎可以肯定这不是我们的初衷。
因为第一个匹配的 case 获胜并且case OKAY始终匹配,所以永远不会检查其他 case 子句。
这解释了错误消息:
SyntaxError: name capture 'OKAY' makes remaining patterns unreachable
Run Code Online (Sandbox Code Playgroud)
我们需要将名称捕获模式替换为非捕获模式,例如使用运算符进行属性查找的值模式.。点是匹配非捕获模式的关键。
有很多方法可以实现这一目标。一种是将名称放在类名称空间中:
class ResponseCode:
OKAY = 200
NOT_FOUND = 404
INTERNAL_SERVER_ERROR = 500
Run Code Online (Sandbox Code Playgroud)
现在,case ResponseCode.NOT_FOUND: ...是一个值模式(因为点)并且不会捕获。
实现相同效果的另一种方法是将常量移动到它们自己的模块中并使用点引用它们:
import response_code
match status:
case response_code.OKAY: ...
case response_code.NOT_FOUND: ...
case response_code.INTERNAL_SERVER_ERROR: ...
Run Code Online (Sandbox Code Playgroud)
除了创建类或模块之外,还可以创建整数枚举来达到相同的效果:
from enum import IntEnum
class ResponseCode(IntEnum):
OKAY = 200
NOT_FOUND = 404
INTERNAL_SERVER_ERROR = 500
Run Code Online (Sandbox Code Playgroud)
对于 HTTP 响应代码,标准库中的HTTPStatus类中已为您创建了一个整数枚举。
这是原始问题的解决方案。.枚举属性查找的存在是将其识别为值模式的匹配和大小写的关键:
from http import HTTPStatus
status = 404
match status:
case HTTPStatus.OK:
print('It worked')
case HTTPStatus.NOT_FOUND:
print('Unknown')
case HTTPStatus.INTERNAL_SERVER_ERROR:
print('Out of service')
case _:
print('Unknown code')
Run Code Online (Sandbox Code Playgroud)