捕获使剩余模式无法访问

Posted

技术标签:

【中文标题】捕获使剩余模式无法访问【英文标题】:Capture makes remaining patterns unreachable 【发布时间】:2021-08-04 02:13:39 【问题描述】:

为什么这段代码会失败:

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')

它会生成此错误消息:

  File "/Users/development/Documents/handler.py", line 66
    case OKAY:
         ^^^^
SyntaxError: name capture 'OKAY' makes remaining patterns unreachable

该错误消息是什么意思?如何修复代码以使其正常工作?

【问题讨论】:

这能回答你的问题吗? How to use values stored in variables as case patterns? 【参考方案1】:

问题原因

case 子句中的变量名被视为name capture pattern。

总是匹配并尝试对变量名进行赋值。这几乎可以肯定不是本意

因为第一个匹配的 case 获胜,并且因为 case OKAY 总是匹配,所以永远不会检查其他 case 子句。

这解释了错误消息:

SyntaxError: name capture 'OKAY' makes remaining patterns unreachable

解决问题的关键

我们需要将名称捕获模式替换为非捕获模式,例如使用. 运算符进行属性查找的value pattern。点是匹配这个非捕获模式的关键。

有很多方法可以实现这一点。一种是将名称放在类命名空间中:

class ResponseCode:
    OKAY = 200
    NOT_FOUND = 404
    INTERNAL_SERVER_ERROR = 500

现在,case ResponseCode.NOT_FOUND: ... 是一个值模式(因为点)并且不会捕获。

实现相同效果的另一种方法是将常量移动到它们自己的模块中并使用点来引用它们:

import response_code

match status:
   case response_code.OKAY: ...
   case response_code.NOT_FOUND: ...
   case response_code.INTERNAL_SERVER_ERROR: ...

除了创建一个类或一个模块,也可以创建一个integer enumeration达到同样的效果:

from enum import IntEnum

class ResponseCode(IntEnum):
    OKAY = 200
    NOT_FOUND = 404
    INTERNAL_SERVER_ERROR = 500

对于 HTTP 响应代码,已经在标准库中的 HTTPStatus 类中为您创建了一个整数枚举。

示例解决方案

这是对原始问题的解决方案。用于枚举属性查找的. 的存在是matchcase 将其识别为value pattern 的关键:

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')
        

【讨论】:

我只是想补充一点,只有case var(如case _)形式的模式才会始终与所有内容匹配。在单个变量的情况下,无论match中的主题是什么形式,都会被捕获。因此,只有match 块中只有1 个case 语句,或者它是最后的语句,才能避免错误。 case [a] 之类的东西只会匹配 1 个元素的列表,但 case a 可以匹配任何类型的任何形式。例如,match [1,2] 不会匹配 case [a],但会匹配 case a。所以case a 形式的模式有点没用。 注: case object(): 也匹配所有内容。

以上是关于捕获使剩余模式无法访问的主要内容,如果未能解决你的问题,请参考以下文章

无法访问的代码 - 尝试捕获 - 最终

未捕获的 ReferenceError:在初始化之前无法访问“GA”

未捕获的错误:引发了跨域错误。 React 无法访问开发中的实际错误对象

iOS 7 横向应用程序无法访问照片库

iframe chrome:未捕获的 DOMException:无法从“Window”读取“localStorage”属性:此文档的访问被拒绝

求助Fiddler 设置https后手机无法访问https网页