-1

Why when I try to return value with warlus and ternary operators := like this:

def get_index(elements: List[int], i: int, boundary: int) -> tp.Optional[int]:
    return x := elements[i] if elements[i] > boundary else None

I get an error.

martineau
  • 119,623
  • 25
  • 170
  • 301
prostak
  • 139
  • 6
  • 2
    And what error do you get? Which Python version are you using? – mkrieger1 Jan 25 '22 at 22:04
  • 1
    You cannot use `return := ` in a return statement, because *it has no purpose and would always be a logical error*. The purpose of `:=` is to have a *local* name for the computed result, so that you can keep working on it in the *local* context. The purpose of `return` is to *leave the local context immediately*. These two goals are fundamentally incompatible. – Karl Knechtel Jan 25 '22 at 22:04
  • 2
    @KarlKnechtel Not quite. `return x if (x := elements[i]) > boundary else None` is legal and make sense, as it only requires indexing `elements` once. – chepner Jan 25 '22 at 22:08
  • Does this answer your question? [What is the correct syntax for Walrus operator with ternary operator?](https://stackoverflow.com/questions/63289494/what-is-the-correct-syntax-for-walrus-operator-with-ternary-operator) (note that this has nothing to do with `return`) – mkrieger1 Jan 25 '22 at 22:11
  • 1
    @Karl Knechtel Nah, `return` isn't necessarily immediately, and you can [use a local variable after `return`](https://tio.run/##K6gsycjPM7YoKPr/PyU1TSFNQ9OKSwEISooqIQwQKEotKS3KU9CoULCyVTAx0gRLpGXmJebkIKkqKMrMK9FQT8/PT0mqTFXXUajQ5OKCCAKN1fz/HwA). – Kelly Bundy Jan 25 '22 at 22:21
  • I can't see examples on tio.run, but now that I think about it, I assume you have in mind something with a `finally` block. @chepner yes, true, which is why I edited :) – Karl Knechtel Jan 25 '22 at 22:23
  • @Karl Knechtel Hmm, why can't you? Yes, using `finally`. – Kelly Bundy Jan 25 '22 at 22:26
  • Noscript, mainly :) I'm just not a fan of those kinds of sites and don't want to add them to my whitelist. – Karl Knechtel Jan 25 '22 at 22:28
  • @Karl Knechtel [Raw pastebin](https://pastebin.com/raw/q9MyGEW2) then. I'm a *huge* fan of tio.run & co. How else do you test other people's code? On your own PC? I don't know how to do that safely. – Kelly Bundy Jan 25 '22 at 22:37
  • @KellyBundy: That's very uncommon usage IMO and regardless, has no real bearing on the question at hand. – martineau Jan 25 '22 at 22:47
  • @martineau Yes, I've never used it myself before and only saw it somewhere once. And yes, I just commented on Karl's "leave immediately" and "fundamentally incompatible", not the question. – Kelly Bundy Jan 25 '22 at 22:53

1 Answers1

1

The comments suggest that you can't use the walrus operator in a return statement, that's incorrect - you just have a syntax error.

This works, but is pointless, as also pointed out in the comments:

from typing import List, Optional


def get_index(elements: List[int], i: int, boundary: int) -> Optional[int]:
    return (x := elements[i] if elements[i] > boundary else None)


print(get_index([1, 2, 3], 2, 1))

All you need is parentheses around the walrus assignment and the value of the expression will be the assigned value.

But why assign to x if all you do is return that value. Instead:

from typing import List, Optional


def get_index(elements: List[int], i: int, boundary: int) -> Optional[int]:
    return elements[i] if elements[i] > boundary else None


print(get_index([1, 2, 3], 2, 1))
Grismar
  • 27,561
  • 4
  • 31
  • 54
  • If it's really intended that you can use the operator here, but need parentheses, that seems like an oversight in the Python grammar. – Karl Knechtel Jan 25 '22 at 22:30
  • @KarlKnechtel if you want to use the outcome of the walrus operator, you always need to use parentheses, for example in `if (x := expression): < do something with x >` - the parentheses are necessary to avoid operator grouping mistakes. It's not an oversight, it is required to avoid breaking the grammar. – Grismar Jan 25 '22 at 22:35
  • 1
    Don't take my word for it though https://www.python.org/dev/peps/pep-0572/#always-requiring-parentheses (in general, whenever you think something is a mistake in the language, it's either legacy from earlier Python versions that could not be avoided, or it's your mistake - the number of people working on the language with PhDs in Computer Science is staggering, mistakes are very rare by now, although every now and then there is one, but they tend to be more obscure and subtle). And if PhDs in CS don't impress, the process behind the language development is very rigorous, so community works. – Grismar Jan 25 '22 at 22:37
  • 1
    @Grismar Not true, `if x := a + b: print(x)` [works just fine](https://tio.run/##K6gsycjPM7YoKPr/P1HBViEJiI0MuTLTFCoUrGwVEhW0FZKsFAqKMvNKNCo0//8HAA). – Kelly Bundy Jan 25 '22 at 22:41
  • And your link goes into the section "**Rejected** alternative proposals". – Kelly Bundy Jan 25 '22 at 22:43
  • @KellyBundy you're right - I chose my example poorly, the parentheses are only required for ambiguous expressions (like the one in OP's question); I'll leave my erroneous comment, so yours make sense; thanks for pointing out the rejection - I misremembered that as making it into the language and didn't properly check context there. It does nothing to change the point (although the confusion may validate KarlKnechtel's point in that there's an argument to be made for either side). The answer is correct either way. – Grismar Jan 25 '22 at 22:46