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

Discussion in 'Python' started by Bo Peng, Jun 19, 2005.

  1. Bo Peng

    Bo Peng Guest

    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
     
    Bo Peng, Jun 19, 2005
    #1
    1. Advertising

  2. Bo Peng

    Peter Hansen Guest

    Peter Hansen, Jun 19, 2005
    #2
    1. Advertising

  3. Bo Peng wrote:

    > 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.
     
    Hsuan-Yeh Chang, Jun 19, 2005
    #3
  4. Bo Peng

    Roy Smith Guest

    Bo Peng <> wrote:
    > 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?
     
    Roy Smith, Jun 19, 2005
    #4
  5. Bo Peng

    Bo Peng Guest

    >>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?


    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
     
    Bo Peng, Jun 19, 2005
    #5
  6. Bo Peng

    Roy Smith Guest

    <d92khl$iop$>, Bo Peng <> wrote:
    > 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.
     
    Roy Smith, Jun 19, 2005
    #6
  7. Bo Peng

    gene tani Guest

    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
     
    gene tani, Jun 19, 2005
    #7
  8. Bo Peng

    Bo Peng Guest

    Roy Smith wrote:

    > 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
     
    Bo Peng, Jun 19, 2005
    #8
  9. Bo Peng

    Roy Smith Guest

    In article <d9461f$olg$>, Bo Peng <> wrote:

    > Roy Smith wrote:
    >
    > > 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.
     
    Roy Smith, Jun 19, 2005
    #9
  10. "Bo Peng" wrote:

    > Roy Smith wrote:
    >
    > > 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
     
    George Sakkis, Jun 19, 2005
    #10
  11. Bo Peng

    Ron Adam Guest

    Bo Peng wrote:
    > Roy Smith wrote:
    >
    >> 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
     
    Ron Adam, Jun 19, 2005
    #11
  12. Bo Peng

    D H Guest

    Peter Hansen wrote:
    > Bo Peng wrote:
    >
    >> I need to pass a bunch of parameters conditionally. In C/C++, I can do
    >> func(cond1?a:b,cond2?c:d,.....)
    >>
    >> Is there an easier way to do this in Python?

    >
    >
    > Please read the FAQ to learn the answer and much other useful ...


    The answer is no. Use if statements.
     
    D H, Jun 20, 2005
    #12
  13. Bo Peng

    Ron Adam Guest

    Ron Adam wrote:

    > 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
     
    Ron Adam, Jun 20, 2005
    #13
  14. Bo Peng

    Peter Hansen Guest

    D H wrote:
    > Peter Hansen wrote:
    >> Bo Peng wrote:
    >>
    >>> I need to pass a bunch of parameters conditionally. In C/C++, I can do
    >>> func(cond1?a:b,cond2?c:d,.....)
    >>>
    >>> Is there an easier way to do this in Python?

    >>
    >> Please read the FAQ to learn the answer and much other useful ...

    >
    > 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
     
    Peter Hansen, Jun 20, 2005
    #14
  15. Bo Peng

    Charles Krug Guest

    On Mon, 20 Jun 2005 06:36:42 GMT, Ron Adam <> wrote:
    > Ron Adam wrote:
    >
    >> 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.
     
    Charles Krug, Jun 20, 2005
    #15
  16. Bo Peng

    D H Guest

    Peter Hansen wrote:
    > D H wrote:
    >
    >> Peter Hansen wrote:
    >>
    >>> Bo Peng wrote:
    >>>
    >>>> I need to pass a bunch of parameters conditionally. In C/C++, I can do
    >>>> func(cond1?a:b,cond2?c:d,.....)
    >>>>
    >>>> Is there an easier way to do this in Python?
    >>>
    >>>
    >>> Please read the FAQ to learn the answer and much other useful ...

    >>
    >>
    >> 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.


    Quit being such an idiot and refuting everything I say. The answer is
    simply no, just use an if statement instead.
     
    D H, Jun 24, 2005
    #16
  17. Bo Peng

    Dave Brueck Guest

    D H wrote:
    > Peter Hansen wrote:
    >>D H wrote:
    >>>Peter Hansen wrote:
    >>>>Bo Peng wrote:

    >>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.


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

    Thanks,
    Dave
     
    Dave Brueck, Jun 24, 2005
    #17
  18. [Dave Brueck]
    > Please keep the discussion civil; please help keep c.l.py a nice place to visit.


    +1

    --
    Richie Hindle
     
    Richie Hindle, Jun 24, 2005
    #18
  19. Bo Peng

    D H Guest

    Dave Brueck wrote:
    > 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 Hansen wrote:
    > Doug, please stop making an idiot of yourself ...[snipped more flames]
     
    D H, Jun 24, 2005
    #19
  20. On Fri, 24 Jun 2005 09:00:04 -0500, D H wrote:

    >> Bo Peng wrote:
    >>
    >>> I need to pass a bunch of parameters conditionally. In C/C++, I can
    >>> do func(cond1?a:b,cond2?c:d,.....)
    >>>
    >>> Is there an easier way to do this in Python?

    >>
    >>

    > 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

    --
    Riccardo Galli
    Sideralis Programs
    http://www.sideralis.net
     
    Riccardo Galli, Jun 24, 2005
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike42
    Replies:
    21
    Views:
    17,412
    Chris Uppal
    Nov 14, 2005
  2. Replies:
    0
    Views:
    352
  3. MotoK
    Replies:
    59
    Views:
    1,922
    Keith Thompson
    Sep 15, 2006
  4. Peng Yu
    Replies:
    8
    Views:
    387
    Steven D'Aprano
    Nov 20, 2009
  5. Patrick Sabin
    Replies:
    1
    Views:
    331
    Paul Rudin
    Nov 20, 2009
Loading...

Share This Page