避免结构模式匹配中的意外捕获
Avoiding accidental capture in structural pattern matching
This example 在使用模式匹配时被认为可能是“问题”:
NOT_FOUND = 400
retcode = 200
match retcode:
case NOT_FOUND:
print('not found')
print(f'Current value of {NOT_FOUND=}')
这是一个使用结构模式匹配的意外捕获示例。它给出了这个意外的输出:
not found
Current value of NOT_FOUND=200
同样的问题以其他形式出现:
match x:
case int():
pass
case float() | Decimal():
x = round(x)
case str:
x = int(x)
在这个例子中,str
需要有括号,str()
。没有它们,它会“捕获”并且 str 内置类型将替换为 x.
的值
是否有defensive programming实践可以帮助避免这些问题并提供早期检测?
最佳实践
Is there a defensive programming practice that can help avoid these problems and provide early detection?
是的。通过始终包含 PEP 634 描述为 irrefutable case block.
的内容,很容易检测到意外捕获
用简单的语言来说,这意味着一个总能匹配的包罗万象的案例。
工作原理
意外捕获总是匹配的。不允许超过一个不可反驳的案例块。因此,当添加有意的 catchall 时,会立即检测到意外捕获。
修正第一个例子
只需在末尾添加一个包罗万象的 wildcard pattern:
match retcode:
case NOT_FOUND:
print('not found')
case _:
pass
立即检测到问题并给出以下错误:
SyntaxError: name capture 'NOT_FOUND' makes remaining patterns unreachable
修复第二个例子
在最后添加一个包罗万象的wildcard pattern:
match x:
case int():
pass
case float() | Decimal():
x = round(x)
case str:
x = int(x)
case _:
pass
再次立即检测到问题:
SyntaxError: name capture 'str' makes remaining patterns unreachable
This example 在使用模式匹配时被认为可能是“问题”:
NOT_FOUND = 400
retcode = 200
match retcode:
case NOT_FOUND:
print('not found')
print(f'Current value of {NOT_FOUND=}')
这是一个使用结构模式匹配的意外捕获示例。它给出了这个意外的输出:
not found
Current value of NOT_FOUND=200
同样的问题以其他形式出现:
match x:
case int():
pass
case float() | Decimal():
x = round(x)
case str:
x = int(x)
在这个例子中,str
需要有括号,str()
。没有它们,它会“捕获”并且 str 内置类型将替换为 x.
是否有defensive programming实践可以帮助避免这些问题并提供早期检测?
最佳实践
Is there a defensive programming practice that can help avoid these problems and provide early detection?
是的。通过始终包含 PEP 634 描述为 irrefutable case block.
的内容,很容易检测到意外捕获用简单的语言来说,这意味着一个总能匹配的包罗万象的案例。
工作原理
意外捕获总是匹配的。不允许超过一个不可反驳的案例块。因此,当添加有意的 catchall 时,会立即检测到意外捕获。
修正第一个例子
只需在末尾添加一个包罗万象的 wildcard pattern:
match retcode:
case NOT_FOUND:
print('not found')
case _:
pass
立即检测到问题并给出以下错误:
SyntaxError: name capture 'NOT_FOUND' makes remaining patterns unreachable
修复第二个例子
在最后添加一个包罗万象的wildcard pattern:
match x:
case int():
pass
case float() | Decimal():
x = round(x)
case str:
x = int(x)
case _:
pass
再次立即检测到问题:
SyntaxError: name capture 'str' makes remaining patterns unreachable