Комментарии 28
Хорошая новость!
+5
Всегда поражало, что в Python нет аналога switch/case. Теперь отпустило :)
+8
Вообще-то есть, легко гуглится, просто имплементируется так, что там больше 10 строк, потому сложнА
-4
И медленнА, и не естественнА и чем так лучше уж без.
А это похоже на switch и читаемость будет получше, но в switch всегда была фишка в быстром сопоставлении, если здесь генерируется код аналогичный лесенке из if-ов(всегда, без оптимизированных исключений), то ценность этой фичи весьма умеренная… а после того как 7-ку дропнули, просто ещё и не светит)
А это похоже на switch и читаемость будет получше, но в switch всегда была фишка в быстром сопоставлении, если здесь генерируется код аналогичный лесенке из if-ов(всегда, без оптимизированных исключений), то ценность этой фичи весьма умеренная… а после того как 7-ку дропнули, просто ещё и не светит)
+2
И медленнА
Вы тестировали? Предоставьте бенчмарки.
и не естественнА
Вам, видимо, яснее, в каком направлении двигаться Python, чтобы было естественно…
-1
Если что, про медленно это про словарь функций… Тестировал. Не быстро. И неестественно. Решение противоречит дзену питона, так что не я решаю))
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 раза… это медленно.
+2
Не понял Capture Patterns.
Как связаны greeting и name?
Как связаны greeting и name?
+1
А, кажется понял. Это просто переменные и второй паттерн срабатывает, когда greeting == name.
+1
Нет, это не так — name будет присвоено (если name не было ранее объявлено, то будет объявлено) значение greeting.
+5
И все равно непонятно причем тут захват. name это переменная, которая существует до match greeting и ее видно в print(f'Hello {name}'), что ожидаемо, ведь match это просто переписанная иначе цепочка if. Так что куда захватывается?
0
не обязательно — name может не существовать до match, и как уже было описано выше, то name будет объявлено со значением, равным greeting.
+1
А в чем смысл? Чем это лучше чем
в случае с 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 с именем? Стрельба в ногу какая-то.
+1
Вчера как раз собрал 3.10.0a6 под Linux. Давно ждал этой штуки. Только пока в VS Code не подвезли поддержку этой конструкции. К примеру — если написать def myfunc(): и нажать Enter, то курсор перенесется на новую строку и отступит 4 пробела. Если же написать match status: и нажать на Enter, то курсор перенесется в начало новой строки. Немного напрягает.
+1
Перечитал примеры дважды, но… аналог switch-case — единственный, понятный с первого взгляда.
Всё остальное, похоже, имеет подводные камни или просто делает не то, что кажется.
Пока что по сравнению с этим цепочка if-else более понятна.
Всё остальное, похоже, имеет подводные камни или просто делает не то, что кажется.
Пока что по сравнению с этим цепочка if-else более понятна.
+6
Не совсем так.
В блоке
cond1 не обязательно тождественно cond2!
Вдобавок cond1 может быть любым условием, а не обязательно условием вида a == b.
Таким образом при match-case варианте меньше когнитивная нагрузка. А снижение когнитивной нагрузки — это всегда хорошо. Мы чаще читаем код, а не пишем его.
В блоке
if cond1:
state1
elif cond2:
state2
else:
state_default
cond1 не обязательно тождественно cond2!
Вдобавок cond1 может быть любым условием, а не обязательно условием вида a == b.
Таким образом при match-case варианте меньше когнитивная нагрузка. А снижение когнитивной нагрузки — это всегда хорошо. Мы чаще читаем код, а не пишем его.
+2
Я не спорю что цепочка 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). Это очень неочевидно и будет провоцировать ошибки.
+7
Секундочку, сопоставление с образцом не будет таковым если его нельзя присвоить переменной(expression vs statement). Если сопоставление с образцом это выражение то это ОК а если statement то это просто кровавый switch на стероидах. Не совсем понятно как это будет сделано.
+6
Оно будет из коробки работать во всех фреймворках? Или нужно будет делать либы?
+1
Саму концепцию сложно назвать новой, она уже реализована во многих языках, причём как нового поколения (Rust, Golang), так и у тех, кому уже за 0x18 (Java).
А можно примерчик паттерн-матчинга в Golang и Java?
+2
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Pattern matching. Теперь и в Python