Есть ли способ проверить, содержит ли итерируемый шаблон шаблон, используя оператор python «match»?

#python #iterable #iterable-unpacking #python-3.10 #structural-pattern-matching

Вопрос:

Это связано с новой бета-версией Python 3.10 и новым match синтаксисом. Есть ли какой-либо способ проверить, содержится ли шаблон просто в повторяющемся? наиболее очевидное решение-просто поместить два подстановочных знака с каждой стороны, но это вызывает SyntaxError проблемы из-за синтаксиса распаковки, возникающего при повторной распаковке.

Есть ли какой-нибудь возможный способ сделать это? ПРИМЕЧАНИЕ: использование таких вещей, как классы-оболочки numbers , в примере было бы хорошо, если бы оно работало с использованием блоков соответствия и было хотя бы несколько читабельным, но я уже пробовал это несколько раз и не имел большого успеха

пример:

 numbers = [1, 2, 3, 5, 7, 8, 9] #does not have to be a list, could be a class if needed

match numbers:
    # this just raises a SyntaxError, but I need a way to do something equivalent to this
    case [*_, (5 | 6), *_]:
        print("match!")
 

Комментарии:

1. как насчет использования любого() ?

2. any() не может использоваться в операторе соответствия, как и любая функция; точная ошибка, которую вы получаете, такова TypeError: called match pattern must be a type

3. со старой версией python : print any([not not re.match(pattern, str(n)) for n in numbers])

4. В чем дело if 5 in numbers or 6 in numbers: ?

Ответ №1:

Нет, в настоящее время у нас нет никаких планов поддерживать повторяющиеся проверки содержимого как часть синтаксиса сопоставления структурных шаблонов.

Лучший способ переписать ваш пример на легальном Python — это обычный if тест:

 if any(i in (5, 6) for i in numbers):
    print("match!")
 

Если проверка сдерживания является лишь одной частью более сложного шаблона, вы можете записать ее в качестве защиты вместо этого:

 match something:
    case [pattern, capturing, numbers] if any(i in (5, 6) for i in numbers):
        print("match!")
 

Конечно, если у вас есть последовательность, также можно найти элемент по известному индексу:

 match numbers:
    case [_, _, _, 5 | 6, *_]:
        print("match at position 3!")
    case [*_, 5 | 6, _, _, _]:
        print("match at position -4!")
 

С учетом сказанного…

использование таких вещей, как классы-оболочки numbers , в примере было бы хорошо, если бы оно работало с использованием блоков соответствия и было хотя бы несколько читабельным

…Я полагаю, что шаблоны отображения могут быть взломаны, чтобы сделать эту работу (при условии, что все ваши элементы хэшируются и не имеют необычных правил равенства).:

 match dict.fromkeys(numbers):
    case {5: _} | {6: _}:
        print("match!")
 

Тем не менее, я настоятельно рекомендую if заполнить эту форму.