0

I am well aware that you can do a one line if else statement in Python, but I am wondering if it is possible to add an or to that. For some reason this does not work, even though it reads like it should. Is there any way to do this:

def write(value):
    return 'That is not a good value' if value is not 1 or 0 #SyntaxError: invalid syntax

EDIT

So that this function would check if the passed in value was the integer 0 or 1, return 'That is not a good value' if it is not, or not return anything if it is. I.E.

write(1) #Nothing
write(2) # That is not a good value
Óscar López
  • 215,818
  • 33
  • 288
  • 367
Startec
  • 10,304
  • 15
  • 74
  • 131
  • 1
    Why do you want to do that? This isn't exactly easy to read and forces a person to read the whole line to understand what it's trying to do. – Tymoteusz Paul Oct 26 '14 at 01:21
  • I can't even tell what you're trying to do after reading the whole line. – Mark Reed Oct 26 '14 at 01:22
  • 1
    possible duplicate of [Does Python have a ternary conditional operator?](http://stackoverflow.com/questions/394809/does-python-have-a-ternary-conditional-operator) – shx2 Oct 26 '14 at 01:33
  • The biggest problem is that you have no `else`. It's never legal to have an `if-else` expression without an `else` part; the `or` doesn't enter into it. It's an *expression*, not a *statement*, and therefore it must have a defined *value*. – Mark Reed Oct 26 '14 at 01:34
  • The reason I asked this was that that question only covers `if else` or the ternary condition. This question has a third condition – Startec Oct 26 '14 at 01:34
  • I'm sorry Mark, I don't quite understand what you mean. – Startec Oct 26 '14 at 01:35
  • This question has no `else` condition at all. I don't even see two conditions, much less three. – Mark Reed Oct 26 '14 at 01:35
  • Perhaps you can explain what value your expression should evaluate to for sample values of `value`. That way it would be easier to understand what you mean. – shx2 Oct 26 '14 at 01:36
  • @Startec: what I mean is, your code has no `else`. The word `else` appears nowhere in your code. You can't have an `if-else` statement without an `else`. Your code is an ex-`else`. It has rung down the curtain and joined the choir invisible... – Mark Reed Oct 26 '14 at 01:37
  • Ahh yes, now I see the confusion. Originally I wanted to check if the value was 1 or 0. If it was not, I wanted to return the value. so I wanted to see is value 1? no! Okay so is the value 0? no! Then return the value. However, the way the question was answered does make it sound like the ternary operator. – Startec Oct 26 '14 at 01:37
  • Regardless of what you're trying to do, you can't have an `if` expression without an `else`. All expressions must have a value, and an `if` expression with no `else` part has no value in the case that the test is false. – Mark Reed Oct 26 '14 at 01:38
  • @Startec the `1 or 0` part is just basic boolean logic that you got wrong. `value == 0 or value == 1` (or, more idiomatic, `value in (0, 1)`) is not the same as `value == 1 or 0`. – Lukas Graf Oct 26 '14 at 01:40
  • Based on your comment where you clarify your requirements (you should probably edit the question instead), there's one important question left unanswered: what exactly do you want to do when the value *is* 1 or 0? – Mark Reed Oct 26 '14 at 01:42
  • The "clarification" actually contradicts the attempt in the question: The question implies `(0, 1)` are good values, whereas the comment says they're not (or why would they be returned?). – Lukas Graf Oct 26 '14 at 01:45
  • Thank you for asking for the clarification. Does my edit and example help? – Startec Oct 26 '14 at 01:46
  • @MarkReed I see your point. Obviously I am a little confused here, because you are right, there is no else clause, I only want to return something if the passed in value is not one of those two values – Startec Oct 26 '14 at 01:49
  • 2
    As @MarkReed explained, an *expression* can't return nothing, it always must return something. You can always return `None` obviously, which is what a function without an explicit return value would return. – Lukas Graf Oct 26 '14 at 01:50
  • I see, I am using this inside of another function to see if the function should continue executing. It should, as long as the value is 1 or 0. Do I need to explicitly add `True` in that case or does `None` work? – Startec Oct 26 '14 at 01:52
  • That of course depends on how you check the function's return value. If you check it like `if write(v) is None` you obviously need to use `None` as your sentinel value for `OK`. If you want to use `42` instead, you can do that too. – Lukas Graf Oct 26 '14 at 01:56
  • what happens if value is not 1 or 0 – Padraic Cunningham Oct 26 '14 at 02:01
  • Thanks for this @LukasGraf, and basically I just want the function to `continue`. I basically my idea was that if the `write` function returned something, the rest of the function would stop (i.e. the parent function). However, if the value was not 0 or 1, nothing would be returned so the parent function would finish. – Startec Oct 26 '14 at 02:06
  • `return value in {1,0} ` `if write(x)` continue in function – Padraic Cunningham Oct 26 '14 at 02:08
  • @Startec that's not how it works, at least not "automatically". Unless you check `write()`'s return value and act on it, the calling function doesn't care about whether it returns something or not. That kind of control flow that you describe could however be achieved by raising your own [exceptions](https://docs.python.org/2/tutorial/errors.html). But this is way beyond getting an `if..else` on one line, you should really create a new question and explain everything that's relevant to your problem there. – Lukas Graf Oct 26 '14 at 02:10
  • Getting more code onto one line is not a good thing, BTW. – Almo Oct 26 '14 at 02:13

2 Answers2

6

Try this:

'That is not a good value' if value not in (0, 1) else None

In the above, we can use the in membership operator to test the equivalent of an orexpression with two or more conditions. Notice that a conditional expression must have an else part (see the documentation). If you don't want to return "anything" you still have to return something. For instance, the empty string '' or None.

Óscar López
  • 215,818
  • 33
  • 288
  • 367
  • 1
    I think the `is` is not needed here, the logic doesn't really call for testing the *identity* of the objects (not the downvoter though) – Marius Oct 26 '14 at 01:25
  • To me this syntax is very succinct and not too long, however, I can see based on the comments not everyone feels that way. Is this not "Pythonic"? – Startec Oct 26 '14 at 01:29
  • I was going to comment that this is the way to do it, but to @Startec, yes, this is the *Pythonic* way to do it. If you want ternary operation, you require the else. – Aaron Hall Oct 26 '14 at 01:30
  • Why use a tuple instead of a list here? Is it just faster? – Startec Oct 26 '14 at 01:30
  • Yes, tuples are faster than lists. see http://stackoverflow.com/questions/26556410/what-to-pass-when-passing-arguments-where-a-list-or-tuple-is-required/26556568#26556568 – Aaron Hall Oct 26 '14 at 01:31
3

There's two problems.

  1. What should that code return if it isn't 0 or 1?
  2. Your conditional is parsed as: value is not (1 or 0)
  3. You really shouldn't compare numbers using is. Use == or !=.

Let's fix it.

def write(value):
    return 'That is not a good value' if value != 1 and value != 0 else 'Great value!'

Or, using a set for clarity:

def write(value):
    return 'That is not a good value' if value not in {0, 1} else 'Great value!'

And, we can see this now working here:

>>> def write(value):
...     return 'That is not a good value' if value not in {0, 1} else 'Great value!'
... 
>>> write(0)
'Great value!'
>>> write(1)
'Great value!'
>>> write(2)
'That is not a good value'
Bill Lynch
  • 72,481
  • 14
  • 116
  • 162
  • 3
    I don't like the use of `is` here, it seems like `!=` is the better comparison. `is` should only be used when we specifically want to test for identity – Marius Oct 26 '14 at 01:28
  • @Marius: I totally agree. I should have fixed that as well. – Bill Lynch Oct 26 '14 at 01:43