Захват делает оставшиеся шаблоны недоступными

Почему этот код не работает:

      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

Что означает это сообщение об ошибке и как исправить код, чтобы он заработал?

2 ответа

Причина проблемы

Имя переменной в предложении case рассматривается как шаблон захвата имени .

Он всегда спичек и пытается сделать задание к имени переменной. Это почти наверняка не то, что было задумано .

Потому что выигрывает первый соответствующий случай и потому что case OKAY всегда совпадает, другие предложения case никогда не проверяются.

Это объясняет сообщение об ошибке:

      SyntaxError: name capture 'OKAY' makes remaining patterns unreachable

Ключ к решению проблемы

Нам нужно заменить шаблон захвата имени шаблоном без захвата, например который использует оператор для поиска атрибутов. Точка - это ключ к совпадению с шаблоном без захвата.

Есть много способов добиться этого. Один из них - поместить имена в пространство имен класса:

      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: ...

Помимо создания класса или модуля, также можно создать целочисленное перечисление для того же эффекта:

      from enum import IntEnum

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

Для кодов ответа HTTP целочисленное перечисление уже создано для вас в классе HTTPStatus из стандартной библиотеки.

Пример решения

Вот отработанное решение исходной проблемы. Наличие .поиск по атрибуту enum является ключом к сопоставлению, и регистр распознает это как шаблоном значения,шаблон значения :

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

Мой совет: если вы используете вопрос, вам нужно написать такой сценарий.

      match (your variable)
    case Hello:
        print('Hi back!')

к:

      match (your variable)
    case 'Hello':
        print('Hi back!')
Другие вопросы по тегам