Комментарии 28
Хорошая новость!
Всегда поражало, что в Python нет аналога switch/case. Теперь отпустило :)
Вообще-то есть, легко гуглится, просто имплементируется так, что там больше 10 строк, потому сложнА
И медленнА, и не естественнА и чем так лучше уж без.
А это похоже на switch и читаемость будет получше, но в switch всегда была фишка в быстром сопоставлении, если здесь генерируется код аналогичный лесенке из if-ов(всегда, без оптимизированных исключений), то ценность этой фичи весьма умеренная… а после того как 7-ку дропнули, просто ещё и не светит)
А это похоже на switch и читаемость будет получше, но в switch всегда была фишка в быстром сопоставлении, если здесь генерируется код аналогичный лесенке из if-ов(всегда, без оптимизированных исключений), то ценность этой фичи весьма умеренная… а после того как 7-ку дропнули, просто ещё и не светит)
И медленнА
Вы тестировали? Предоставьте бенчмарки.
и не естественнА
Вам, видимо, яснее, в каком направлении двигаться Python, чтобы было естественно…
Если что, про медленно это про словарь функций… Тестировал. Не быстро. И неестественно. Решение противоречит дзену питона, так что не я решаю))
Pattern matching соответствует, но цепочка if-ов это по прежнему не быстро.
результат:
ifs test average by 1000 reps: 1908833 ns
switcher test average by 1000 reps: 7090622 ns
В 3.5 раза… это медленно.
Pattern matching соответствует, но цепочка if-ов это по прежнему не быстро.
import time
def switcher(condition):
lambdadict = {13:lambda x, y: x+y,
12:lambda x, y: x*y,
16:lambda x, y: x/y,
1:lambda x, y: x**y}
return lambdadict[condition] if condition in lambdadict else lambda x, y: x
def test_switcher(inp):
A = 0
for n,i,j in inp:
A += switcher(n)(i, j)
return A
def test_ifs(inp):
A = 0
for n,i,j in inp:
if n == 1: A += i**j
elif n == 12: A += i*j
elif n == 13: A += i+j
elif n == 16: A += i/j
else: A += i
return A
funcs = (1, 12, 13, 16, 2432)
inp = [(funcs[n % 5], funcs[n % 5]//3, n) for n in range(10000)]
test_ifs(inp)
test_switcher(inp)
times = 0
A = 0
for i in range(1000):
t1 = time.perf_counter_ns()
A += test_ifs(inp)
times += time.perf_counter_ns() - t1
times /= 1000
print('ifs test average by 1000 reps: %i ns' %times)
times = 0
A = 0
for i in range(1000):
t1 = time.perf_counter_ns()
A += test_switcher(inp)
times += time.perf_counter_ns() - t1
times /= 1000
print('switcher test average by 1000 reps: %i ns' %times)
input('any')
результат:
ifs test average by 1000 reps: 1908833 ns
switcher test average by 1000 reps: 7090622 ns
В 3.5 раза… это медленно.
Не понял Capture Patterns.
Как связаны greeting и name?
Как связаны greeting и name?
А, кажется понял. Это просто переменные и второй паттерн срабатывает, когда greeting == name.
Нет, это не так — name будет присвоено (если name не было ранее объявлено, то будет объявлено) значение greeting.
И все равно непонятно причем тут захват. name это переменная, которая существует до match greeting и ее видно в print(f'Hello {name}'), что ожидаемо, ведь match это просто переписанная иначе цепочка if. Так что куда захватывается?
не обязательно — name может не существовать до match, и как уже было описано выше, то name будет объявлено со значением, равным greeting.
А в чем смысл? Чем это лучше чем
в случае с wildcard хоть работает ожидаемо. А в случае с case name — переменная name может существовать выше, а позже быть переименована и case name начинает работать как wildcard с именем? Стрельба в ногу какая-то.
match greeting:
case "":
print('Hello my friend')
case _:
print(f'Hello {greeting}')
в случае с wildcard хоть работает ожидаемо. А в случае с case name — переменная name может существовать выше, а позже быть переименована и case name начинает работать как wildcard с именем? Стрельба в ногу какая-то.
Вчера как раз собрал 3.10.0a6 под Linux. Давно ждал этой штуки. Только пока в VS Code не подвезли поддержку этой конструкции. К примеру — если написать def myfunc(): и нажать Enter, то курсор перенесется на новую строку и отступит 4 пробела. Если же написать match status: и нажать на Enter, то курсор перенесется в начало новой строки. Немного напрягает.
Перечитал примеры дважды, но… аналог switch-case — единственный, понятный с первого взгляда.
Всё остальное, похоже, имеет подводные камни или просто делает не то, что кажется.
Пока что по сравнению с этим цепочка if-else более понятна.
Всё остальное, похоже, имеет подводные камни или просто делает не то, что кажется.
Пока что по сравнению с этим цепочка if-else более понятна.
Не совсем так.
В блоке
cond1 не обязательно тождественно cond2!
Вдобавок cond1 может быть любым условием, а не обязательно условием вида a == b.
Таким образом при match-case варианте меньше когнитивная нагрузка. А снижение когнитивной нагрузки — это всегда хорошо. Мы чаще читаем код, а не пишем его.
В блоке
if cond1:
state1
elif cond2:
state2
else:
state_default
cond1 не обязательно тождественно cond2!
Вдобавок cond1 может быть любым условием, а не обязательно условием вида a == b.
Таким образом при match-case варианте меньше когнитивная нагрузка. А снижение когнитивной нагрузки — это всегда хорошо. Мы чаще читаем код, а не пишем его.
Я не спорю что цепочка if-else более универсальна.
Но речь о случае, когда условия действительно однородны.
В частности, особенно проблематичны sequence и mapping patterns.
По мне так if len(args) == 2 and ('kwarg' in kwargs): понятнее, чем предлагаемый синтаксис, даже с поправкой на лишнюю пару строчек для распаковки искомых значений.
Capture Patterns — это огромная мина замедленного действия, потому что вынос литерала в константу резко меняет поведение кода но только для некоторых случаев (если имя — не dotted name). Это очень неочевидно и будет провоцировать ошибки.
Но речь о случае, когда условия действительно однородны.
В частности, особенно проблематичны sequence и mapping patterns.
По мне так if len(args) == 2 and ('kwarg' in kwargs): понятнее, чем предлагаемый синтаксис, даже с поправкой на лишнюю пару строчек для распаковки искомых значений.
Capture Patterns — это огромная мина замедленного действия, потому что вынос литерала в константу резко меняет поведение кода но только для некоторых случаев (если имя — не dotted name). Это очень неочевидно и будет провоцировать ошибки.
Секундочку, сопоставление с образцом не будет таковым если его нельзя присвоить переменной(expression vs statement). Если сопоставление с образцом это выражение то это ОК а если statement то это просто кровавый switch на стероидах. Не совсем понятно как это будет сделано.
Оно будет из коробки работать во всех фреймворках? Или нужно будет делать либы?
Саму концепцию сложно назвать новой, она уже реализована во многих языках, причём как нового поколения (Rust, Golang), так и у тех, кому уже за 0x18 (Java).
А можно примерчик паттерн-матчинга в Golang и Java?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Pattern matching. Теперь и в Python