Python 3.10 совпадение / регистр с константами
Я попытался заменить блок кода if / elif / elif/.../else на более короткий
match/case
из Python 3.10. У меня определены три константы, и я хочу сделать для каждой что-то свое, поэтому мой код выглядит примерно так:
>>> const_a = 1
>>> const_b = 2
>>> const_c = 3
>>> interface = const_b # example
>>> match interface:
... case const_a:
... print("case a")
... case const_b:
... print("case b")
... case const_c:
... print("case c")
Однако при запуске этого кода будет исключение:
File "<stdin>", line 2
SyntaxError: name capture 'const_a' makes remaining patterns unreachable
Что я делаю неправильно?
2 ответа
В
match...case
это больше, чем просто
switch...case
. Из https://www.python.org/dev/peps/pep-0622/#patterns :
- А захват картина выглядит как х и эквивалентен идентичной цель назначения: она всегда соответствует и связывает переменную с заданным (простым) именем.
- Постоянное значение шаблон работает как буквальный , но и для некоторых именованных констант. Обратите внимание, что это должно быть полное имя (с точками), учитывая возможную двусмысленность с шаблоном захвата. Он выглядит как Color.RED и соответствует только значениям, равным соответствующему значению. Это никогда не связывает.
Итак, вам нужно будет создать объект, который имеет эти переменные в качестве атрибутов и использовать квалифицированные имена в совпадении.
import types
consts = types.SimpleNamespace()
consts.A = 1
consts.B = 2
consts.C = 3
interface = 2
match interface:
case consts.A:
print("A")
case consts.B:
print("B")
case consts.C:
print("C")
Который, как и ожидалось, печатает
B
Для получения дополнительной информации о том , почему , см. Https://www.python.org/dev/peps/pep-0622/#alternatives-for-constant-value-pattern.
[Примечание: этот ответ является полностью гипотетическим]
FWIW, вот как я бы сделал совпадение / регистр - мне кажется гораздо более интуитивным, чем получение новых переменных практически с нуля и отсутствие разумной возможности использовать переменные для сравнения или реальные константы:
Альтернативное предложение соответствия / случая
""" abstract example to showcase the design """
SOME_CONSTANT = 0
some_string = "qwert"
def example_matchcase (number):
# using an alias/abbreviation with 'as'
match var as $:
# simple literal case
case 10:
print("case 1")
# basic check including another variable
case len(some_string):
print("case 2")
# check against a constant
case SOME_CONSTANT:
print("case 3")
# if-like statement
case ? 0 < var < 10:
print("case 4")
# using the abbreviation
case ? callable($):
print("case 5")
case ? hasattr($, 'isnumeric') and $.isnumeric()
print("case 6")
# slide statement
case ? $ < 50:
print("case 7a")
slide
case ? $ < 25:
print("case 7b")
slide
case ? $ < 10:
print("case 7c")
slide
# alias for improved readability
case ? $ in (1,3,5,7) as early_prime:
print("case 8 - early prime:", early_prime)
# 'else' instead of 'case _:'
# more meaningful and avoids confusion with the gettext _
else: # or use case $:
print("unknown value")
# if you are using returns, you could put a default here
""" real-world example where this would be very elegant """
INTERF_MUPDF = 0
INTERF_PDFIUM = 1
INTERF_POPPLER = 2
def render_thumbnails (interface):
match interface as $:
case INTERF_MUPDF:
from interfaces import InterfMupdf
_interface = InterfMupdf()
case INTERF_PDFIUM:
from interfaces import InterfPdfium
_interface = InterfPdfium()
case INTERF_POPPLER:
from interfaces import InterfPoppler
_interface = InterfPoppler()
case ? callable($):
print("using a custom interface")
_interface = interface
else:
raise Exception("`interface` must be a constant or a callable object")