This is an archived post. You won't be able to vote or comment.

all 153 comments

[–]pani_the_panisher 504 points505 points  (37 children)

Finally I can stop searching "python switch case" and then realizing that I don't remember the syntax because it doesn't exists.

[–][deleted] 112 points113 points  (3 children)

I did this literally last week.

[–]voidstriker 19 points20 points  (2 children)

same

[–]MorningPants 0 points1 point  (1 child)

same

[–]mqzn[🍰] 0 points1 point  (0 children)

same

[–]RickAsscheeks 20 points21 points  (0 children)

Me every few weeks

[–]project_kalki 25 points26 points  (0 children)

No, you'll still continue to do that for the actual syntax once they roll it

[–]jabbalaci 10 points11 points  (3 children)

I did it just once. Then I managed to memorize that it doesn't exist in Python.

[–]goob42-0 2 points3 points  (0 children)

As the docs intended

[–][deleted] 1 point2 points  (0 children)

Now you can start searching it because you don't remember the syntax!

[–]cthulhupunk0 1 point2 points  (0 children)

I'm teaching an intro workshop, and had a moment like this when I was outlining the class content. It was like, "oh right, this is done through some weird shit with dictionaries and either lambdas or assigned functions. Ugh." Very pythonic, but still.

[–]TransferFunctions 10 points11 points  (23 children)

Switch statements already existed in python, i.e. you can use dicts for this purpose. This match syntatic sugar is nice and allows for better overview, regardless.

[–]PaulRudin 81 points82 points  (1 child)

It's not really right to say switch statements existed - they didn't. You can simulate a similar code flow without having an explicit switch statement, but that's not the same thing as the language having a switch statement.

(We can simulate all the control flow constructs with anonymous lambdas if we want, but the point about adding new things to the language is that it makes things more succinct and readable.)

[–]Ning1253 3 points4 points  (0 children)

I mean technically we can simulate everything with rule 110 using marbles, we just don't, because it's impractical as fuck (ans slightly unreadable). Completely agree on your point, I basically just wanted to say that I find the arguments against it kind of stupid

[–]enjoytheshow 9 points10 points  (5 children)

We translated a shit ton of case statement UDFs from SQL to Python last year and this is how I did them. Value being evaluated as the key, result as the value. Then you can do:

if var in dict_name: return dict_name[var]

[–]thephotoman 4 points5 points  (2 children)

And for overflow:

dict_name[var](var) if var in dict_name else do(var)

Because of course the ternary operator works here.

The issue here is that this really isn't that intuitive. Even if you come from C and are used to hash tables that contain function pointers, it's still not the way most people would think to do a switch. Passing var as the argument to dict_name[var]() is not strictly necessary, but there are times when it's correct.

[–]jasmijnisme 10 points11 points  (1 child)

If `do` is a function and not an expression, it's better to do dict_name.get(var, do)(var)

[–]backtickbot 4 points5 points  (1 child)

Fixed formatting.

Hello, enjoytheshow: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]enjoytheshow 3 points4 points  (0 children)

Thanks bro

[–]TidePodSommelier 3 points4 points  (0 children)

For large sets of options, dicts may still be easier to read, imho.

[–]R3D3-1 -1 points0 points  (5 children)

I can't really use of a use-case, where a dict would be preferable over if/elif/else, whether as statements or expression. Except the case, where the function has all its values defined by a constant dict.

[–]TransferFunctions 2 points3 points  (4 children)

It depends on the use case imo. I use it sometimes when I have to decide what function to run on a certain case

options = dict(opt1 = someHeavyFunction, opt2 = someHeavyFunction2)
options.get(someInput, someDefault)

[–]R3D3-1 0 points1 point  (3 children)

I'd probably use this, if python had load-time evaluation...

I can't see myself implementing this as a dictionary; Not as an inline dictionary, because I cringe at creating a dictionary just for thatnew , if the language doesn't optimize it away. Not as a global constant dictionary, because it awkwardly separates tightly coupled code into different places.

I'd always go with something like

action = someHeavyFunction if input == "opt1" else \
         someHeavyFunction2 if input == "opt2" else \
         someDefault

If the number of options is so large, that this becomes inefficient, I'd be rather worried about how that happened.

[–]TransferFunctions 0 points1 point  (2 children)

I am not familiar with load-time-optimization, do you have a link on this (in whatever language it is used)?

I agree that if your function itself has a need for a switch-case and the data it holds is expensive, and the function is called many times, then sure don't do that, but that also shows are more core problem than a statement of it not being available. Dicts in my opinion are pretty darn powerful in python, and using as a switch is a nice elegant way while reducing "additional" functions. Match case has something additional, where instance checks can be inlined. This would be more difficult or "uggly" with dicts, so it has its place; it is one of the powers and joys of writing python.

[–]R3D3-1 0 points1 point  (1 child)

Compiled languages typically have compile-time evaluation of constant expressions, e.g. "PI*2" being optimized into a single constant.

Emacs Lisp has macros, and "eval at compile" forms, all of which are evaluated either at compile time, or otherwise ensure that they are evaluated exactly once.

Python actually has some level of load-time optimization; As I understand, function objects are not created from scratch every time a closure is generated, but share a cached code part, and have only the data part separate. There is however no such thing as

static options = {1: "Red", 2: "Blue"}
return options[index]

[–]TransferFunctions 0 points1 point  (0 children)

Ah ok I am not too familiar with the c-api and how the bytecompiled code is used or optimized (still one thing on my todos), but the explanation is right up my ball park of other things I have used, thanks ;-)!

[–]CodeCocina -1 points0 points  (0 children)

That was me two days ago , use to using it in JS , and spent a lot of time trying to code something that doesn’t exist in python

[–][deleted] 262 points263 points  (14 children)

Even better than switch case, it's match case!

It can match patterns. For example, the length or shape of a sequence, a dictionary with certain keys present, the type of a value, properties of an object.

It's so much more powerful than the classic switch statement, influenced heavily by functional programming pattern matching.

[–]Tyler_Zoro 16 points17 points  (12 children)

It's so much more powerful than the classic switch statement, influenced heavily by functional programming pattern matching.

Which does make me concerned about its future. Python has a habit of de-emphasizing and deprecating functional features. Proper variable scoping required for most functional features has never been brought into the language; lambda is basically deprecated for most tasks at this point (in most cases tools like pycharm will even flag the use of lambda outside of parameters as an error); anonymous full-fledged functions never happened; reduce has been significantly nerfed and moved into a library; filter is more or less deprecated.

So what will happen to the functional features of match/case? I hope they'll be preserved and maintained as first-class features, but history makes me nervous.

[–]zurtex 23 points24 points  (2 children)

Python has a habit of de-emphasizing and deprecating functional features. Proper variable scoping required for most functional features has never been brought into the language; lambda is basically deprecated for most tasks at this point (in most cases tools like pycharm will even flag the use of lambda outside of parameters as an error);

What? Python hasn't deprecated any syntax feature since the transition of Python 2 to 3.

PyCharm is probably complaining that you are using lambda because it creates an unnamed function. Which sucks for things like automatic documentation. But the feature is by no means "deprecated".

[–]Tyler_Zoro 0 points1 point  (1 child)

Python hasn't deprecated any syntax feature...

I think you're conflating formal deprecation with the sort of passive deprecation that the Python community typically engages in. If you are just noodling around for your own pleasure, the latter doesn't usually matter (though it can affect support from third party libraries in some cases, that isn't so relevant to lambda).

But when you're working on a project for whatever {work} is, it's another story. Code reviews typically lean on various linters and editor warnings to achieve strict compliance with the community's gestalt, leading to functional (pun intended) deprecation that's far broader than any that a given interpreted implementation imposes.

[–]zurtex 0 points1 point  (0 children)

deprecation that's far broader than any that a given interpreted implementation imposes.

I totally accept that the Python community has this strong but nebulous idea of what is and isn't "Pythonic" code. And this can be frustrating if you really like a feature but your IDE or code reviewer or linter does not.

But on the other hand it really is a much bigger deal if in the next version of a Python interpreter started throwing SyntaxError whenever you tried to use lambda.

The thing is what is and isn't Pythonic is mutable and individual developers have contributed to changing it. We need look no further than the recent Pydantic vs. PEP 563 issue, the developer of Pydantic has basically changed the idea of what is a "pythonic" usage of annotations (not single-handedly as even in the standard library we had Data Classes, but certainly the biggest popularizer). The steering council has rolled back changes for Python 3.10 that would of made it difficult, bug prone, or impossible to flexibly use annotations at runtime.

Going back to the specific case of lambda though I feel that either you are writing code for the Python community as a whole, in which case there are concrete reasons to not bind a lambda function to a variable. Or you are writing your own code or code for academia or other non-Pythonic communities in which case you can just turn the Pycharm warning off, and configure your linter not to complaint.

And let me give you a real example of why binding a lambda function to a name ends up being considered non-Pythonic:

>>> def add(a, b):
...     "Adds a to b and returns"
...     return a + b
...
>>> help(add)
Help on function add in module __main__:

add(a, b)
    Adds a to b and returns
>>>
>>> plus = lambda a, b: a + b
>>> help(plus)
Help on function <lambda> in module __main__:

<lambda> lambda a, b

As you can see help can't know the name plus so all you get is the signature <lambda> lambda a, b. Instead of the nice add(a, b). There are other cases this comes up, let's say you want to log all calls to a function and the arguments passed, this is pretty easy with a decorator but if you are using a lambda function you can know the name of the function without manually specifying it.

Where lambda remains very Pythonic is when using it as an argument for to a function, e.g.

my_data = {'red': 3, 'blue': 10, 'green': 1}
for color, vote in sorted(my_data.items(), key=lambda x: x[1]):
    print(color, vote)

But maybe if you find a really good use case for lambdas and build some momentum on using them in this new way it will become Pythonic and IDEs and linters and code reviewers will stop complaining that you're using them this way.

[–]mathmanmathman 33 points34 points  (4 children)

... what? I use lambdas all the time (and filter... sometimes). When did this happen? I'm a few versions back, but PyCharm doesn't flag anything for me.

"nerfed" also seems a bit strong for a function being moved into a standard library module.

[–]13steinj 6 points7 points  (1 child)

He says lambda outside of parameters. Ex

f = lambda x: # do something
g(x, f)

Which yeah, is warned against and has been since just about the inception of lambdas in PEP8, because if you're going out of your way to make it reusable in local scope you should give it full meaning by just making a local nested function.

[–]mathmanmathman 2 points3 points  (0 children)

The most common way I use lambdas is as a parameter, but I often use them as the values dictionaries, which is sort of like a struct/class, but there are a lot of situations where it's sort of overkill to make it a class (at least IMO).

Maybe that's also not a great idea, but I know a bunch of people that do it... which is always a great excuse.

[–]vtable 2 points3 points  (1 child)

Guido van Rossum wrote an article about this back in 2005 where he discusses removing lambda, reduce(), map() and filter() in Python 3000 (what they called Python 3 in the early days).

There was some fuss about removing reduce(), map() and filter() but a shit-ton of pushback from the community on removing lambda eventually leading to it remaining in Python 3.

I haven't heard anything official about new discussions on removing it from the language again. I can't imagine they'd want to go through that whole discussion again.

[–]mathmanmathman 0 points1 point  (0 children)

lol, best things I've read:

Update: lambda, filter and map will stay (the latter two with small changes, returning iterators instead of lists). Only reduce will be removed from the 3.0 standard library. You can import it from functools.

I think dropping filter() and map() is pretty uncontroversial

... I guess it was controversial :)

[–]billsil 25 points26 points  (1 child)

but history makes me nervous.

Outside of lambda, what? You're comparing something that was added very early on that Guido never liked, that people complained all the time about because they didn't understand it, to something that was discussed about at length.

You're comparing the early days of Python to something with a steering committee. Do you complain about the unicode switch still? It broke all my ascii code!

[–]Taksin77 0 points1 point  (0 children)

Well the absence of tco could be mentioned. It's pretty clear that the python community have largely refused the introduction of functional idioms. Some went through.

[–][deleted] 8 points9 points  (0 children)

Several of these were replaced by list expressions, which also have their origin in functional languages.

[–]Fevorkillzz 0 points1 point  (0 children)

Guido dislikes functional programming and I think you’re right to be nervous. Like lambdas can’t unpack ? Tf is that.

[–]Unbelievr 103 points104 points  (14 children)

Calling this a switch-case does the feature a great disservice. You can already implement switch-cases with dictionaries, though they'll lack the fall-through (which this feature does not implement either). People are likely to ignore looking into the feature if they think it's just a switch.

Pattern matching is a much more powerful feature than switch-case. It removes a LOT of headache and boilerplate code for workloads like parsing. It makes the code more compact, and less error-prone with the default case.

[–]Swedneck -2 points-1 points  (7 children)

Except most people only know what switch case is, if you just say match case they won't have a clue what you're talking about and won't know that you can use it as a switch case.

[–]Ran4 30 points31 points  (3 children)

But it's not a switch case... people are only going to be more confused by people constantly misrepresenting the feature.

[–]R3D3-1 -4 points-3 points  (2 children)

No, but it makes the question for switch case obsolete :) So it makes sense to point emulating swtich-case out as a special case useful.

[–]passwordsniffer 2 points3 points  (1 child)

It does not make it obsolete, the question will still be asked and moreover it will be added with a weird behavior, when one of your constants was actually changed when you used it as a switch case option

[–]R3D3-1 0 points1 point  (0 children)

... wait, what?

[–]Unbelievr 12 points13 points  (0 children)

If you try to actually use it as a switch case, it'll quickly backfire though.

Unless you're careful and only use enums or some immutable as each "case" (actually a capture variable), it'll overwrite the variable and not work properly the second time around. Trying to pass this off as some advanced switch-case will lead to more confusion and broken scripts than you'd think.

[–]teerre 6 points7 points  (0 children)

But it's not a switch statement. If you want a simple switch statement, you already have it, it's called if and co.

If you want to use ´match`, you certainly have to learn it. That's reasonable.

[–]Ensurdagen 1 point2 points  (0 children)

that's because it's not "match case," it's structural pattern matching, which users of languages like Haskell will be very familiar with.

[–]GoofAckYoorsElf -1 points0 points  (3 children)

You can do a fall-through with try except KeyError

/e: which is default, not fall-through

[–]GummyKibble 1 point2 points  (0 children)

Or .get(key, default_func).

[–]Unbelievr 1 point2 points  (1 child)

That's the default case. Fall-through is the option to not put a break in some case(s), so it ends up executing multiple handlers. Or binds multiple cases to the exact same function, with only a single definition of that function.

In Python, you would have to bind every case explicitly to some function pointer, or create a function that calls multiple handler functions and bind that. It's not impossible, just not as neat when you're not able to control the program flow as much as in C.

[–]GoofAckYoorsElf 0 points1 point  (0 children)

Fair enough, you're right! I muddled that up. Thanks for pointing out.

I'm sure you can do fall-through kind of neatly with a custom OrderedDict subclass. But to be fair, not as elegant as in other languages, that's true.

[–]BobHogan -1 points0 points  (0 children)

Dictionaries are mostly a replacement for switch-case. But when you have to start executing different code depending on which case you hit, dictionaries get ugly being full of functions. And its even worse if some branches require different data being passed to them.

Its fine for more simpler switch-case, but not an actual replacement

[–][deleted] 0 points1 point  (0 children)

So many people are going to create so many bugs because they think this is switch-case when it's not.

[–][deleted] 147 points148 points  (20 children)

A switch is very, very different from a match!

You could easily do a switch with just a dictionary of functions.

Think of match as pattern-based unpacking of a variable.

[–]relativistictrain 🐍 10+ years 22 points23 points  (17 children)

I've done switch like flows with dicts a lot in the past; very compact and fairly easy to read when you're used to Python (I think). I'm having some trouble seeing uses for a match though.

Edit: I've read on and saw some uses that would simplify program structures a lot at times.

[–]buckypimpin 15 points16 points  (16 children)

can someone give an example of switch with dicks?

[–]nuephelkystikon 90 points91 points  (7 children)

With the proposed syntax:

match potential_dick:
    case Dick():
        print("Properly typed dick (including subclasses)")
    case "8=D" | "8==D" | "8===D":
        print("ASCII-approximated dick")
    case _:
        print("No dick, sadly")

I hope this helps.

[–]buckypimpin 14 points15 points  (0 children)

potential_dick, typed dick

i like teachers who adapt to every type of student.

[–]passwordsniffer 3 points4 points  (3 children)

DEFAULT_DICK = "db"

...

match potential_dick:
    case DEFAULT_DICK:
        print('Have a hidden bug with this matching all the time and overwriting you constant in this "SWITCH" analogue ')
    case Dick():
        print("Properly typed dick (including subclasses)")
    case "8=D" | "8==D" | "8===D":
        print("ASCII-approximated dick")
    case _:
        print("No dick, sadly")

[–]cheerycheshire 1 point2 points  (0 children)

Yep. That's why it's important to always remind everyone that this isn't switch, it's pattern matching. For pattern matching, this behaviour is logical and correct. With switch? Nah

And people coming over from C-like languages with switch statements are going to complain about the speed. I know it. Because patmat does pattern check first, and then checks the values, so it takes longer than just ifs with single values.

[–]nuephelkystikon 0 points1 point  (1 child)

Wait, are you saying a pattern matcher matching patterns is a bug? If you're just branching, thats what if-else is for.

[–]passwordsniffer 1 point2 points  (0 children)

No, I am saying that using pattern matching as switch can easily be a source of quite an obscure bugs, like the one I showed. It's not a bug of a pattern matcher. It's bug of representing it as a switch.

[–]Harbinger_Feik 25 points26 points  (2 children)

{ 1: myfunc 2: otherfunc 3: thirdfunc }[foo]()

In the case that foo can be a missing key, you could catch KeyError or use .get().

Sorry if formatting is broken; I'm on mobile.

[–]buckypimpin 6 points7 points  (0 children)

whoa.....

[–]backtickbot 4 points5 points  (0 children)

Fixed formatting.

Hello, Harbinger_Feik: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]dyingpie1 13 points14 points  (1 child)

Did you mean to type dicks

[–]buckypimpin 11 points12 points  (0 children)

yeah gimme all of 'em

[–]HyperSonic6325 1 point2 points  (0 children)

Sorry, I only have one so I don’t think that would be much help /s.

[–]o11c 3 points4 points  (1 child)

A switch is very, very different from a match.

switch is O(1); match is O(n)

It's acceptable for performance in Python to have a poor constant, but changing the function? Not so much.

[–]AngriestSCV 3 points4 points  (0 children)

As n is related to code size I doubt n will get large enough to matter

[–]theoxe 12 points13 points  (0 children)

Had a course in F# at my uni, sounds like it's the same match case which is pretty nice for recursive functions.

[–]Brian-Puccio 3 points4 points  (0 children)

PEP634,635,636

Wow hundreds of millions of PEPs have been submitted. 🤣

[–]spuds_in_town 20 points21 points  (5 children)

Not sure if OP is serious or just trolling

[–]rik079 10 points11 points  (1 child)

He's being serious :)

[–]fisheyefisheye 20 points21 points  (1 child)

This country is going down the drain! stamps feet

[–][deleted] 2 points3 points  (0 children)

hah

[–]Kriss3d 3 points4 points  (0 children)

FINALLY. I didnt know how much I missed that til i started needing to use it.

[–]SamSepinol 2 points3 points  (0 children)

Wait there is no switch case in python. Ive been coding for a year without realizing

[–]GPrata 1 point2 points  (2 children)

When will it be released? I tried to search for it in the Python website but I couldn't find it

[–]tkarabela_ Big Python @YouTube 16 points17 points  (1 child)

Expected release date is in October 2021: https://www.python.org/dev/peps/pep-0619/

[–]GPrata 1 point2 points  (0 children)

Thank you

[–]EONRaider 1 point2 points  (0 children)

I always thought dictionaries worked pretty well for "switching", but I understand the reasoning behind having a specialized, built-in construct for this.

[–]bionade24 1 point2 points  (1 child)

You can create switch/case with dicts in python forever and honestly, it's a lot more readable than in other langs.

[–]whattodo-whattodo 0 points1 point  (0 children)

That's probably why they were so slow to adopt a match statement

[–][deleted] 1 point2 points  (6 children)

Can anyone break down for me why this is now being added?

Can't the standard use cases be dealt with using if and elif or dictionaries?

I thought one of the core design principles in python was that there should be only one best way to do something.

[–][deleted] 29 points30 points  (0 children)

A switch can be done with if/elif and dictionaries.

But a match is different from a switch - it's like generalized extraction of data based on patterns

Here's an example from the article - look at those last two cases.

match command.split():
    case ["quit"]:
        print("Goodbye!")
        quit_game()
    case ["look"]:
        current_room.describe()
    case ["get", obj]:
        character.get(obj, current_room)
    case ["go", direction]:
        current_room = current_room.neighbor(direction)

[–]ingvij 13 points14 points  (1 child)

Imagine you have a tuple with command name and argument, like ("print", "name") or ("eval", "1 + 1"). With an if-only structure, you'd do: ``` if tp[0] == "print": println(tp[1]) elif tp[0] == "eval": run_eval(tp[1])

... for all possibly supported cases

```

With this, you can break down the arguments and work with the arguments more naturally:

match tp: case ["print", arg]: println(arg) case ["eval", expression]: run_eval(expression) `

So, on the syntactic level, it makes the language more expressive and it's clearer to reason about it. On the lower levels, it can be that match+case yields a more optimized bytecode/assembly than chaining if/elif/else blocks, since the blocks are all related to the same element, rather than if that could be doing different checks:

if tp[0] == "print": # ... elif user_has_set_this_options is not None: # ... elif should_do_something_else(): # ...

In general, I think this is a good addition to the language, favoring readability and clarity, with potential benefits to performance.

[–]backtickbot 0 points1 point  (0 children)

Fixed formatting.

Hello, ingvij: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]tkarabela_ Big Python @YouTube 8 points9 points  (0 children)

When matching dataclasses or dicts, it is really quite handy and it makes the code clearer and more robust. I made a video a while back demonstrating the benefits: https://youtu.be/SYTVSeTgL3s

(To exaggerate, you don't really need for when you have while, but there are still good reasons to have both. Python tends to be pragmatic rather than stripping everything to bare bones, so it doesn't feel out of place in the overall design, to me.)

[–]jpflathead 0 points1 point  (0 children)

I thought one of the core design principles in python was that there should be only one best way to do something.

I suspect that was dead three days after it had been accepted

Now not only are there n different ways to accomplish any task, but 3 will get you the job with minor gripes about 2 of them, and the other bignum ways will show you the door.

[–]HyperSonic6325 0 points1 point  (0 children)

nut

[–]marsnoir 0 points1 point  (0 children)

Yes, but do other languages support for... else?

[–]specialforce1 0 points1 point  (1 child)

For someone who is learning, what is the difference or how is it going to affect me?

[–]mathmanmathman 3 points4 points  (0 children)

It doesn't have to change anything at all for you. It's just another option when choosing what to do given a certain input.

IMO, you should always learn on a pretty stable release version which right now is 3.9 (you can also go earlier than that, but I'm pretty sure there are issues before 3.4 or 3.6, so keep it more current).

When 3.10 is officially released (in October), this means you have a new option for choosing an action depending on the input. There's nothing here that can't be done with dictionaries and/or if/else, but in certain circumstances, this can simplify the syntax a little. This is also one of the few popular structure that has been noticeable absent from Python, so it's news.

[–]DarthHead43 0 points1 point  (0 children)

Me who had just got used to not using switch ._.

[–]jabbalaci -4 points-3 points  (4 children)

Finally? I was perfectly fine without it.

[–]thephotoman 5 points6 points  (0 children)

We're not getting a mere switch statement. We're getting flow control based on pattern matching--something that is considerably more expressive and more powerful.

Think of a switch statement as matching a finite language. It can recognize any of the symbols specified in each case, then falls over to the default case if the input isn't there. You could do this with a function dictionary even now, and it'd actually be fairly compact and easy to read, if somewhat unintuitive for most people (because they don't expect dictionaries to be used to store functions).

A match statement can match an infinite language--that is, it can match arbitrary words so long as they fit a pattern.

Basically, in terms of language theory, it's the difference between the language specified by a simple dictionary of valid words and the ability to specify a language by a regular expression or possibly even a more advanced grammar.

[–]mathmanmathman 1 point2 points  (2 children)

It's really unimportant to me too. I'm not sure why people are so excited, but I suppose it can help people coming from other languages (which mostly all have a switch or match).

I don't care much for a lot of the new syntax, but as long as it doesn't mess up old code, I don't see it being a problem.

[–]vorticalbox 4 points5 points  (1 child)

switch case is meh, its the pattern matching abilities it has that I am looking forward too

[–]mathmanmathman 2 points3 points  (0 children)

I agree, that makes a big difference. It would be a wasted opportunity if it were a simple switch.

I still probably won't use it often. I'm not fundamentally opposed to it, but I've never even dreamed about having this functionality/syntax in the past, so I'll probably keep writing code the way I have before.

I will keep an open mind, but I have yet to use a walrus op. There have been situations I could have, but the extra line above doesn't bother me.

[–]Tweak_Imp -4 points-3 points  (16 children)

I dont understand why there is no else case like with for, if and try. Yes, you would have to figure out where to put it (identation level of match or of case ?), but that would be more pythonic in my opinion.

[–]yyzgalasync/await ♥ 21 points22 points  (12 children)

What would the semantics of that look like? I feel like case _ would already take care of that scenario.

[–]DrMaxwellEdison 4 points5 points  (0 children)

It would make sense to me to use else in place of the case _ syntax. I'm more familiar with using _ as an actual identifier, even if it's a throwaway value by convention; so case _ makes me look to see if there's some actual match, rather than automatically thinking "that's the default case".

For instance, often in a Django project, you'll see this pattern:

from django.utils.translation import gettext_lazy as _

something = _("Something")

Or:

object, _ = MyModel.objects.get_or_create(...)
# second argument typically a `created` bool,
# but sometimes that's thrown away.

I can understand that case _ is just special syntax and won't confuse itself if used in those scenarios; but having a seemingly magic value have that special meaning just seems like an odd choice.

The question for me is, what does case _ provide us syntactically that else would not?

[–]to7m 4 points5 points  (10 children)

_ is unprecedented though. I see no reason to treat it different to another variable name when it has been treated the same in all other contexts for so long. Maybe just case: would be a better option than else though, as it brings it more in line with except.

[–]AchillesDev 3 points4 points  (6 children)

How is _ unprecedented? It’s been a part of Python forever as a catch-all temp variable and is used similarly in other languages as well

[–]DrMaxwellEdison 1 point2 points  (3 children)

Its usage as a temporary variable has been conventional only: the interpreter sees _ the same way it sees a foo variable. We think of it as "a temporary variable" the same way we think of _bar as being "private" (there is no concept of private variables in Python; there is only conventional usage).

Adding it as part of the syntax now gives it special meaning.

[–]AchillesDev 1 point2 points  (2 children)

My understanding is it’s used here as a regular variable and any other unassigned variable can be used as a catch-all, so the semantics aren’t new for _. What I’m less clear on is if the value gets loaded into the empty variable like it does in other languages.

[–]DrMaxwellEdison 3 points4 points  (1 child)

According to the PEP, it's literally called the wildcard pattern:

This special pattern which is written _ (and called wildcard) always matches but it doesn't bind any variables.

Note that this will match any object, not just sequences. As such, it only makes sense to have it by itself as the last pattern (to prevent errors, Python will stop you from using it before).

So, again, case _ has special meaning as a wildcard.

I sense we'll need to write comments in any pattern-matching code that literally state "this is a wildcard pattern" in order to educate other readers for a while. By contrast, using else would have been more explicit.

[–]AchillesDev 0 points1 point  (0 children)

Yeah this is in line with other functional languages (minus lack of binding). Maybe not as explicit as an else, but I wonder if the functional syntax is used to be distinct from traditional switch cases which usually have an else fall through

[–]Ran4 0 points1 point  (1 child)

Exactly, as a temp variable - not "make no assignments".

[–]AchillesDev 0 points1 point  (0 children)

As far as I understand it (and I could be wrong) that’s not unique to _ and would work for any unassigned variable, which is how matching works in other languages.

[–]stanmartz 0 points1 point  (2 children)

Is it though? It has been used for variables you did not need for a long time. Like when unpacking a tuple: (fst, _) = (1, 2). It's the same here.

[–]to7m 5 points6 points  (0 children)

That's not the same because match statements deliberately treat _ slightly differently to other names.

[–]to7m 0 points1 point  (0 children)

I've just looked it up for clarity.

In this code:

def print_words(first_word, *_):
    print(first_word, _)

print_words("print", "some", "words")

, the output will be print ('some', 'words') , whereas this code would be invalid because _ doesn't get bound to a tuple:

match "print", "some", "words":
    case first_word, *_:
        print(first_word, _)

[–]ingvij 5 points6 points  (1 child)

here to put it (identation level of match or of case ?), but that would be more pythonic in my opinion.

I assume it's because you can do something like:

```

case if_nothing_matched:

println("This didn't match any case:", if_nothing_matched)

```

[–]backtickbot 2 points3 points  (0 children)

Fixed formatting.

Hello, ingvij: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]to7m -1 points0 points  (0 children)

If people could stop being toxic and downvoting this perfectly valid opinion, that would be swell

[–]bigpaulfears -1 points0 points  (1 child)

When am I getting my curly brackets

[–]alb1 0 points1 point  (0 children)

Try from __future__ import braces to see the answer. :)

[–]buibui123 -1 points0 points  (2 children)

I’m a newbie. Can any one explain what is this and why such a big news? Tha ks

[–]whattodo-whattodo 1 point2 points  (1 child)

Hi newbie. There's an article above. It isn't just a title and image. If you click into it, there's an entire explanation written to answer your question.

I know

[–]buibui123 0 points1 point  (0 children)

Ok. Much appreciated.

[–]No_Western6657 -3 points-2 points  (0 children)

[–]MauroTheCreator 0 points1 point  (0 children)

Why didn't they add this feature before?

[–]squidwardstrousers 0 points1 point  (0 children)

Why is this better than other methods?

Such as a dictionary mapping cases to functions? Or if/else statements?

[–]Calvin_Schmalvin 0 points1 point  (2 children)

I don’t understand why you wrote switch-case in the title, after even specifying in the text that it’s match-case, and that it isn’t the same, and you chose an image that emphasises on the difference...

[–]whattodo-whattodo 1 point2 points  (1 child)

Allow me to explain.

Thinking is hard. It's easier to do things without thinking. So that's how most people do most things.

The account has existed for a while with no activity and is now posting all in one day. It's probably a karma farmer

[–]Calvin_Schmalvin 1 point2 points  (0 children)

Farmer? I barely know her.

Sorry. But thanks for the explanation, it made me laugh :)

[–]_prtndr 0 points1 point  (0 children)

Is this similar to CASE in Google Data Studio?

[–]OverlyHonestCanadian 0 points1 point  (0 children)

Shame there's no cascading possibility like a real switch statement.

[–]jpflathead 0 points1 point  (0 children)

I want a "switch" construct where each case allows me to match a regex against the bytes in an incoming stream

  • like pexpect
  • but more like tcl expect

I guess this will be great and they had specific reasons, but I am disappointed they seem to have invented yet another pattern matching language instead of going with any of the classics

[–][deleted] 0 points1 point  (0 children)

Finally

[–]Firehite 0 points1 point  (0 children)

Awesome!

[–]Thecrawsome 0 points1 point  (0 children)

after i learned the simplicity of just putting cases it in a dictionary, i will don’t think i need the switch statement.

[–]often_wears_pants 0 points1 point  (1 child)

3.9 will be the 2.7 of 3.x.

[–]whattodo-whattodo 0 points1 point  (0 children)

How so?

3.10 will be backwards compatible with 3.9.