Can I use a conditional in a variable declaration?

V

volcs0

I've done this in Scheme, but I'm not sure I can in Python.

I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in this more compact form:


a = (if a == "yes": "go ahead": "stop")


is there such a form in Python? I tried playing around with lambda
expressions, but I couldn't quite get it to work right.
 
K

Kent Johnson

I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in this more compact form:


a = (if a == "yes": "go ahead": "stop")

If the value for the 'true' case can never have a boolean value of
False, you can use this form:

a = (a == "yes") and "go ahead" or "stop"

The short-circuit evaluation of 'and' and 'or' give the correct result.
This will not work correctly because the 'and' will always evaluate to
"" which is False so the last term will be evaluated and returned:

a = (a == "yes") and "" or "stop"

and IMO the extra syntax needed to fix it isn't worth the trouble; just
spell out the if / else.

Kent
 
B

Ben Cartwright

I've done this in Scheme, but I'm not sure I can in Python.

I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in this more compact form:


a = (if a == "yes": "go ahead": "stop")


is there such a form in Python? I tried playing around with lambda
expressions, but I couldn't quite get it to work right.

There will be, in Python 2.5 (final release scheduled for August 2006):

See:
http://mail.python.org/pipermail/python-dev/2005-September/056846.html
http://www.python.org/doc/peps/pep-0308/

--Ben
 
V

volcs0

Kent - Thanks for the quick reply. I tried the and/or trick - it does
work. But you're right - more trouble than its worth.... So for now, I
did it "the long way". It looks like (see below), this functionality
will be added in soon.

Thanks for the quick help.

-sam
 
P

Paul Rubin

a = (if a == "yes": "go ahead": "stop")

is there such a form in Python? I tried playing around with lambda
expressions, but I couldn't quite get it to work right.

This has been the subject of huge debate over the years. The answer
is Python doesn't currently have it, but it will be added to a coming
version: See http://www.python.org/doc/peps/pep-0308/

To do it in the most general way with lambda expressions, use (untested):

a = (lambda: iffalse_expression,
lambda: iftrue_expression)[bool(condition)]()

That makes sure that only one of the target expressions gets evaluated
(they might have side effects).

There are various more common idioms like

a = (condition and iftrue_expression) or iffalse_expression

which can go wrong and evaluate both expressions. It was a bug caused
by something like this that led to conditional expressions finally
being accepted into Python.
 
J

Jeffrey Schwab

I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in this more compact form:

a = (if a == "yes": "go ahead": "stop")

is there such a form in Python? I tried playing around with lambda
expressions, but I couldn't quite get it to work right.

Rather than lambda, this merits a named function. You only have to
define it once.

def mux(s, t, f):
if s:
return t
return f

def interpret(a):
answer = mux(a == "yes", "go ahead", "stop")
print answer

interpret("yes") # Prints "go ahead."
interpret("no") # Prints "stop."
 
R

Ron Adam

I've done this in Scheme, but I'm not sure I can in Python.

I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in this more compact form:


a = (if a == "yes": "go ahead": "stop")


is there such a form in Python? I tried playing around with lambda
expressions, but I couldn't quite get it to work right.


I sometimes find it useful to do:


answers = {True: "go ahead", False: "stop"}

answer = answers[a == "yes"]



This is also sometimes useful when you want to alternate between two values.

values = {'a':'b', 'b':'a'} # define outside loop

while 1:
v = values[v] # alternate between 'a' and 'b'
...

There are limits to this, both the keys and the values need to be hashable.


Cheers,
Ron
 
G

Georg Brandl

Jeffrey said:
Rather than lambda, this merits a named function. You only have to
define it once.

def mux(s, t, f):
if s:
return t
return f

But be aware that this is not a complete replacement for a syntactic
construct. With that function, Python will always evaluate all three
arguments, in contrast to the and/or-form or the Python 2.5 conditional.

You can show this with

test = mux(False, 1/0, 1)

and

test = False and 1/0 or 1

Georg
 
A

andy

I've done this in Scheme, but I'm not sure I can in Python.

I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in this more compact form:


a = (if a == "yes": "go ahead": "stop")


is there such a form in Python? I tried playing around with lambda
expressions, but I couldn't quite get it to work right.
How about:

a = ["stop","go ahead"][a == "yes"]

This works because:
0

Taking into account all the previous comments - both the literal list
elements are evaluated; there is no short-cirtuiting here. If they're
just literals, it's no problem, but if they're (possibly
compute-intensive) function calls, it would matter. I find the list
evaluation easier to parse than the and/or equation, and in instances
where that would be necessary, I will use the longhand if ... else ...
structure for readability.

hth,
-andy
 
J

Jeffrey Schwab

Georg said:
But be aware that this is not a complete replacement for a syntactic
construct. With that function, Python will always evaluate all three
arguments, in contrast to the and/or-form or the Python 2.5 conditional.

Absolutely true, and I should have mentioned it. In languages that
allow ?: syntax, I rarely rely on its short-circuit effect, but it
certainly is a significant difference.
 
S

Sion Arrowsmith

Ron Adam said:
I want the equivalent of this:

if a == "yes":
answer = "go ahead"
else:
answer = "stop"

in [a] more compact form:
I sometimes find it useful to do:

answers = {True: "go ahead", False: "stop"}
answer = answers[a == "yes"]

In this particular case, you can get it even more compact as

answer = {"yes": "go ahead"}.get(a, "stop")

but that's sacrificing elegance and readability for bytes. When I find
myself with code like the OP's, I usually rewrite as:

answer = "stop"
if a == "yes":
answer = "go ahead"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top