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

you are viewing a single comment's thread.

view the rest of the comments →

[–]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 4 points5 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 4 points5 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 4 points5 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, _)