简体   繁体   English

避免结构模式匹配中的意外捕获

[英]Avoiding accidental capture in structural pattern matching

This example is being discussed as likely "gotcha" when using pattern matching:在使用模式匹配时,这个例子被讨论为可能的“陷阱”:

NOT_FOUND = 400

retcode = 200
match retcode:
    case NOT_FOUND:
        print('not found')  

print(f'Current value of {NOT_FOUND=}')

This is an example of accidental capture with structural pattern matching.这是使用结构模式匹配意外捕获的示例。 It gives this unexpected output:它给出了这个意想不到的 output:

not found
Current value of NOT_FOUND=200

This same problem comes up in other guises:同样的问题以其他形式出现:

match x:
    case int():
        pass
    case float() | Decimal():
        x = round(x)
    case str:
        x = int(x)

In this example, str needs to have parentheses, str() .在此示例中, str需要有括号str() Without them, it "captures" and the str builtin type is replaced with the value of x .没有它们,它会“捕获”并将str内置类型替换为x的值。

Is there a defensive programming practice that can help avoid these problems and provide early detection?是否有一种防御性编程实践可以帮助避免这些问题并提供早期检测?

Best practice最佳实践

Is there a defensive programming practice that can help avoid these problems and provide early detection?是否有一种防御性编程实践可以帮助避免这些问题并提供早期检测?

Yes.是的。 Accidental captures are easily detected by always including what PEP 634 describes as an irrefutable case block .通过始终包含 PEP 634 所描述的无可辩驳的案例块,可以轻松检测到意外捕获。

In plain language, that means a catchall case that always matches.用简单的语言来说,这意味着一个总是匹配的包罗万象的案例。

How it works这个怎么运作

Accidental captures always match.意外捕获始终匹配。 No more than one irrefutable case block is permitted.不允许超过一个无可辩驳的案例块。 Therefore, accidental captures are detected immediately when an intentional catchall is added.因此,当添加有意的包罗万象时,会立即检测到意外捕获。

Fixing the first example修复第一个示例

Just add a catchall wildcard pattern to the end:只需在末尾添加一个通用通配符模式

match retcode:
    case NOT_FOUND:
        print('not found')
    case _:
        pass

That detects the problem immediately an gives the following error:立即检测到问题并给出以下错误:

SyntaxError: name capture 'NOT_FOUND' makes remaining patterns unreachable

Fixing the second example修复第二个示例

Add a catchall wildcard pattern to the end:在末尾添加一个通用通配符模式

match x:
    case int():
        pass
    case float() | Decimal():
        x = round(x)
    case str:
        x = int(x)
    case _:
        pass

Again the problem is detected immediately:再次立即检测到问题:

SyntaxError: name capture 'str' makes remaining patterns unreachable

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM