Is there something similar to ?: operator (C/C++) in Python?

B

Bo Peng

Hi,

I need to pass a bunch of parameters conditionally. In C/C++, I can do

func(cond1?a:b,cond2?c:d,.....)

In Python, I am using temporary variables like

if cond1:
para1 = a
else:
para1 = b

# ....
# a bunch of such if/else

func(para1, para2,...)

Is there an easier way to do this in Python?

BTW, I do not want to use the following since all of a,b,c,d etc will be
evaluated.

def condValue(cond, val1,val2):
if cond:
return val1
else:
return val2

func(condValue(cond1,a,b), condValue(cond2,c,d),...)

Thanks.
Bo
 
H

Hsuan-Yeh Chang

Bo said:
Hi,

I need to pass a bunch of parameters conditionally. In C/C++, I can do

func(cond1?a:b,cond2?c:d,.....)

In Python, I am using temporary variables like

if cond1:
para1 = a
else:
para1 = b

# ....
# a bunch of such if/else

func(para1, para2,...)

Is there an easier way to do this in Python?

BTW, I do not want to use the following since all of a,b,c,d etc will be
evaluated.

def condValue(cond, val1,val2):
if cond:
return val1
else:
return val2

func(condValue(cond1,a,b), condValue(cond2,c,d),...)

Thanks.
Bo

take a look at how to use "lambda" in python.
 
R

Roy Smith

Bo Peng said:
I need to pass a bunch of parameters conditionally. In C/C++, I can do

func(cond1?a:b,cond2?c:d,.....)

Python does not have a ternary operator analogous to C's :?. There are
some ugly hacks you can play with the logical operators to emulate :?, but
in my opinion, the cure is worse than the disease.
In Python, I am using temporary variables like

if cond1:
para1 = a
else:
para1 = b

# ....
# a bunch of such if/else

func(para1, para2,...)

Yeah, that's how I would do it. How many of these things do you have?
 
B

Bo Peng

In Python, I am using temporary variables like
Yeah, that's how I would do it. How many of these things do you have?

I have around 10 of them. Using these if/else, it will take 50 lines for
a function call. It also bothers me to have 10 variables left in the
namespace, in addition to finding 10 meaningful names.

The FAQ provides two solutions, neither of them are elegant. I guess I
will use if/else for reasability purpose.

Thanks.
Bo
 
R

Roy Smith

I have around 10 of them. Using these if/else, it will take 50 lines for
a function call. It also bothers me to have 10 variables left in the
namespace, in addition to finding 10 meaningful names.

If you've got 10 different conditional branches in a single function,
that's pretty messy logic no matter what language you write it in or what
syntactic sugar you've got to let you write it compactly. Can you give us
some idea of what it is that you're trying to do? It pretty unusual to see
a requirement like that.
The FAQ provides two solutions, neither of them are elegant. I guess I
will use if/else for reasability purpose.

I agree that the and/or hack is ugly, and I generally stay away from it
because I think if/else is easier to read and understand. But if you've
got 10 of them, the compactness (and, as you say, avoiding having to create
10 temp variables) of the and/or probably means the hack is worth doing.
Somthing like:

myComplicatedFunction (cond1 and value1a or value1b,
cond2 and value2a or value2b,
cond3 and value3a or value3b,
cond4 and value4a or value4b,
cond5 and value5a or value5b,
cond6 and value6a or value6b,
cond7 and value7a or value7b,
cond8 and value8a or value8b,
cond9 and value9a or value9b,
cond10 and value10a or value10b)

is kind of ugly, but at least you only have to understand what's going on
with the and/or ONCE, and then you can apply that understanding to the 10
repetitions of the construct. Having 50 lines of if/else makes it much
harder to get your head around what's going on.
 
G

gene tani

If your test variable has specific values to branch on, the standard
way is to have those values be keys in a dictionary, and do:

branched_func_obj = dict_of_values.get(testvar)

And the lambda hack is here, courtesy of Peter Norvig

http://www.norvig.com/python-iaq.html
 
B

Bo Peng

Roy said:
Can you give us some idea of what it is that you're trying to do? It pretty unusual to see
a requirement like that.

def func(type_of_obj1, type_of_obj2, .....):
callfunc( [
type_of_obj1 and obj1a() or obj1b(),
type_of_obj2 and obj2a() or obj2b(),
....
])

callfunc can take arbitrary number of objects whose types are determined
by type_of_obj1 etc. I was using a bunch of if/else to create objects
and pass them to callfunc.

Since type_of_obj1 etc are usually binary and obj1a() etc will never be
false, the and/or solution does not look so bad in this case.

Thanks.
Bo
 
R

Roy Smith

Roy said:
Can you give us some idea of what it is that you're trying to do? It
pretty unusual to see
a requirement like that.

def func(type_of_obj1, type_of_obj2, .....):
callfunc( [
type_of_obj1 and obj1a() or obj1b(),
type_of_obj2 and obj2a() or obj2b(),
....
])

I'm still not sure what the big picture is, but I suspect if you're
switching on object types, you're doing something wrong, or at least
unpythonic.
 
G

George Sakkis

Bo Peng said:
Roy said:
Can you give us some idea of what it is that you're trying to do? It pretty unusual to see
a requirement like that.

def func(type_of_obj1, type_of_obj2, .....):
callfunc( [
type_of_obj1 and obj1a() or obj1b(),
type_of_obj2 and obj2a() or obj2b(),
....
])

callfunc can take arbitrary number of objects whose types are determined
by type_of_obj1 etc.

Unless the obj_i_a and obj_i_b are totally unrelated (very unlikely), I
think this might/should be refactored so that the decision between each
obj_i_a and obj_i_b is done in a separate obj_i_factory callable. If
you provide an example or two of specific triples (type_of_obj_i,
obj_i_a, obj_i_b), we'll have a better idea of whether factories are an
overkill in this case or not.

George
 
R

Ron Adam

Bo said:
Roy said:
Can you give us some idea of what it is that you're trying to do? It
pretty unusual to see a requirement like that.


def func(type_of_obj1, type_of_obj2, .....):
callfunc( [
type_of_obj1 and obj1a() or obj1b(),
type_of_obj2 and obj2a() or obj2b(),
....
])

callfunc can take arbitrary number of objects whose types are determined
by type_of_obj1 etc. I was using a bunch of if/else to create objects
and pass them to callfunc.

Since type_of_obj1 etc are usually binary and obj1a() etc will never be
false, the and/or solution does not look so bad in this case.

Thanks.
Bo

Are you matching the order to the obj_type?

objlist = [ (type_obj1, obj1a, obj2b),
(typ_obj2, obj2a, obj2b),
etc...]

objs = [type_of_obj1, type_of_obj2, etc...]

for n in range(len(objs)):
if objs[n] == objlist[n][0]:
objlist[n][1]()
else:
objlist[n][2]()


What significance does the order have?


You might be able to use a dictionary of tuples.

call_obj = {(type_obj1,0):eek:bj1a,
(type_obj1,0):eek:bj1b,
(type_boj2,1):eek:bj2a,
(type_obj2,1):eek:bj2b,
etc... }
call_obj[(type_of_obj,order)]()


Regards, Ron
 
R

Ron Adam

Ron said:
You might be able to use a dictionary of tuples.

call_obj = {(type_obj1,0):eek:bj1a,
(type_obj1,0):eek:bj1b,
(type_boj2,1):eek:bj2a,
(type_obj2,1):eek:bj2b,
etc... }
call_obj[(type_of_obj,order)]()


Regards, Ron

This won't work like I was thinking it would.


But to get back to your is there a ? operator question...

Try this.

def foo():
return "foo"

def boo():
return "boo"

print (foo, boo)[1>0]() # prints "boo"
print (foo, boo)[1<0]() # prints "foo"

Regards,
Ron
 
P

Peter Hansen

D said:
The answer is no. Use if statements.

Actually that's just one possible answer. Whether it's _the_ answer is
obviously again a matter of opinion, and as usual we differ.

Doug, please stop making an idiot of yourself by offering simplistic
"corrections" to every one of my posts. I realize you don't like me,
and that's too bad, but that isn't a good reason to be rude when I try
to be helpful to someone or to offer my opinion on some issue. It's
downright immature.

A better alternative would simply be to provide your own response to the
OP, instead of appearing to be trying to correct me, and leave it to
others to figure out for themselves which piece of advice they prefer.
Given that I'm hardly a troll around here, and do find ways of providing
useful advice from time to time, I believe I deserve the courtesy of a
bit of respect.

(I'd have emailed Doug about this many a time, but it doesn't appear he
uses a real email address here so I'm forced to respond in a public
forum. Sorry for the waste of bandwidth, and regardless of the response
I won't bring it up again.)

-Peter
 
C

Charles Krug

Ron said:
You might be able to use a dictionary of tuples.

call_obj = {(type_obj1,0):eek:bj1a,
(type_obj1,0):eek:bj1b,
(type_boj2,1):eek:bj2a,
(type_obj2,1):eek:bj2b,
etc... }
call_obj[(type_of_obj,order)]()


Regards, Ron

This won't work like I was thinking it would.

But to get back to your is there a ? operator question...

Try this.

def foo():
return "foo"

def boo():
return "boo"

print (foo, boo)[1>0]() # prints "boo"
print (foo, boo)[1<0]() # prints "foo"

Regards,
Ron

Another thought:

Often complicated conditional logic is a flag that we need to refactor.
An accounting package I built has an official list of approved vendors,
but allows users to provisionally add a new vendor, which is corrected
later.

The bulk of this system only understands, "This document has-a vendor"
with a "vendor factory" that returns the appropriate type of vendor.

All of the logic specific to the specific subclass is internal to the
subclasses themselves.
 
D

D H

Peter said:
Actually that's just one possible answer. Whether it's _the_ answer is
obviously again a matter of opinion, and as usual we differ.

Quit being such an idiot and refuting everything I say. The answer is
simply no, just use an if statement instead.
 
D

Dave Brueck

D said:
Quit being such an idiot and refuting everything I say. The answer is
simply no, just use an if statement instead.

Please keep the discussion civil; please help keep c.l.py a nice place to visit.

Thanks,
Dave
 
D

D H

Dave said:
Please keep the discussion civil; please help keep c.l.py a nice place
to visit.

You didn't see Peter Hansen's previous post to which I made my reply, so
I'd like to extend your recommendation to *everyone* here.

Peter said:
> Doug, please stop making an idiot of yourself ...[snipped more flames]
 
R

Riccardo Galli

The answer is simply no, just use an if statement instead.

That's not true.
One used form is this:
result = cond and value1 or value2

which is equal to
if cond:
result=value1
else:
result=value2


another form is:

result = [value2,value1][cond]


the first form is nice but value1 must _always_ have a true value (so not
None,0,'' and so on), but often you can handle this.

Bye,
Riccardo
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top