Tertiary Operation

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • abcd

    #1

    Tertiary Operation

    x = None
    result = (x is None and "" or str(x))

    print result, type(result)

    ---------------
    OUTPUT
    ---------------
    None <type 'str'>


    y = 5
    result = (y is 5 and "it's five" or "it's not five")

    print result

    -------------
    OUTPUT
    -------------
    it's five

    ....what's wrong with the first operation I did with x? I was expecting
    "result" to be an empty string, not the str value of None.

  • Richard Brodie

    #2
    Re: Tertiary Operation


    "abcd" <codecraig@gmai l.comwrote in message
    news:1161091832 .088769.279630@ b28g2000cwb.goo glegroups.com.. .
    >x = None
    result = (x is None and "" or str(x))
    >
    ...what's wrong with the first operation I did with x? I was expecting
    "result" to be an empty string, not the str value of None.
    Your evil tertiary hack has failed you because the empty string
    counts as false in a boolean context. Please learn to love the
    new conditional expression syntax:




    Comment

    • Tim Chase

      #3
      Re: Tertiary Operation

      x = None
      result = (x is None and "" or str(x))
      >
      print result, type(result)
      >
      ---------------
      OUTPUT
      ---------------
      None <type 'str'>
      >
      >
      y = 5
      result = (y is 5 and "it's five" or "it's not five")
      >
      print result
      >
      -------------
      OUTPUT
      -------------
      it's five
      >
      ...what's wrong with the first operation I did with x? I was expecting
      "result" to be an empty string, not the str value of None.
      An empty string evaluates to False, so it then continues to the
      other branch. Either of the following should suffice:

      # return a non-empty string
      x is None and "None" or str(x)

      # invert the logic and return
      # something in the "and" portion
      x is not None and str(x) or ""

      There are more baroque ways of writing the terniary operator in
      python (although I understand 2.5 or maybe python 3k should have
      a true way of doing this). My understanding is that one common
      solution is something like

      {True: "", False: str(x)}[x is None]

      -tkc



      Comment

      • Carsten Haese

        #4
        Re: Tertiary Operation

        On Tue, 2006-10-17 at 09:30, abcd wrote:
        x = None
        result = (x is None and "" or str(x))
        >
        print result, type(result)
        >
        ---------------
        OUTPUT
        ---------------
        None <type 'str'>
        The "condition and result1 or result2" trick only works if result1 is an
        expression with a True boolean value. The empty string has a false
        boolean value.

        You could force result1 to have a true boolean value by sticking it into
        a list thusly:

        result = (x is None and [""] or [str(x)])[0]

        But that's ugly. Use Python 2.5 where there is a true conditional
        expression or find another way to solve your problem.

        -Carsten


        Comment

        • abcd

          #5
          Re: Tertiary Operation

          Carsten Haese wrote:
          Use Python 2.5 where there is a true conditional
          expression or find another way to solve your problem.
          python 2.5 once we upgrade (hopefully soon), anyways...an earlier post
          suggested the inverse...

          x = None
          result = (x is not None and str(x) or "")

          which works just fine.

          thanks.

          Comment

          • Steven D'Aprano

            #6
            Re: Tertiary Operation

            On Tue, 17 Oct 2006 06:30:32 -0700, abcd wrote:
            x = None
            result = (x is None and "" or str(x))
            Boolean operators "and" and "or" stop as soon as a result is known. So:

            X and Y evaluates as X if X is false; otherwise it evaluates as Y.
            X or Y evaluates as X if X is true; otherwise it evaluates as Y.

            (x is None) evaluates as true, so (x is None and "") evaluates as "".
            ("") evaluates as false, so ("" or str(None)) evaluates as str(None).

            The important factor you missed is, I think, that the empty string is
            false in a boolean context.
            >>if '':
            .... print "empty string evaluates as true"
            .... else:
            .... print "empty string evaluates as false"
            ....
            empty string evaluates as false

            y = 5
            result = (y is 5 and "it's five" or "it's not five")
            (y is 5) evaluates as true, so (y is 5 and "it's five") evaluates as "it's
            five".
            "it's five" evaluates as true, so ("it's five" or ""it's not five")
            evaluates as "it's five".


            Your basic logic is okay, but you shouldn't test equality with "is".

            == tests for equality;
            is tests for object identity.

            In the case of None, it is a singleton; every reference to None refers to
            the same object. But integers like 5 aren't guaranteed to be singletons.
            In your case, you were lucky that, by a fluke of implementation, "y is 5"
            was true. But watch:
            >>1+4 is 5
            True
            >>10001 + 10004 == 10005
            True
            >>10001 + 10004 is 10005
            False

            Always use == to test for equality, and (is) only to test for actual
            object identity ("is this object the same as this one, not just two
            objects with the same value?").


            --
            Steven.

            Comment

            • Roy Smith

              #7
              Re: Tertiary Operation

              In article <1161093117.541 719.320210@i3g2 000cwc.googlegr oups.com>,
              "abcd" <codecraig@gmai l.comwrote:
              Carsten Haese wrote:
              Use Python 2.5 where there is a true conditional
              expression or find another way to solve your problem.
              >
              python 2.5 once we upgrade (hopefully soon), anyways...an earlier post
              suggested the inverse...
              >
              x = None
              result = (x is not None and str(x) or "")
              >
              which works just fine.
              >
              thanks.
              Why not just:

              if x is None:
              result = str(x)
              else:
              result = ""

              It's a couple more lines of code, but it's obvious what it means. I know
              about boolean short-circuit evaluation, and the and/or trick, but I still
              look at

              result = (x is not None and str(x) or "")

              and have to puzzle through exactly what's going on there. You are going to
              write your code once. It's going to be read many many times by different
              people. It's worth a few more keystrokes on your part to save all those
              future maintenance programmers headaches later.

              You won't really understand just how important readability is until you're
              maintaining a million lines of old code, most of it written by people who
              are no longer on the project. I spend a lot of time staring at code
              somebody else wrote and muttering things like, "What the **** does this
              do?" That's just money down the toilet.

              If I have to reach for a reference manual to look up operator binding rules
              to understand a piece of code, that's bad. If I have to start making notes
              on a piece of scrap paper, "Let's see, if x is this, then that's true, so
              blah, blah", that's bad. If I look at something subtle, don't realize it's
              subtle, and come to an incorrect conclusion about what it does, then base
              some other decisions on that incorrect conclusion, that's really, really
              bad.

              Comment

              • Christophe

                #8
                Re: Tertiary Operation

                abcd a écrit :
                x = None
                result = (x is None and "" or str(x))
                >
                print result, type(result)
                >
                ---------------
                OUTPUT
                ---------------
                None <type 'str'>
                >
                >
                y = 5
                result = (y is 5 and "it's five" or "it's not five")
                >
                print result
                >
                -------------
                OUTPUT
                -------------
                it's five
                >
                ...what's wrong with the first operation I did with x? I was expecting
                "result" to be an empty string, not the str value of None.
                >
                the "<condition and <if_trueor <if_false>" is NOT a ternary operator
                but an ugly hack that breaks in some situations. It just happens that
                you stumbled on one of those situations : <if_truemust never evaluate
                as False. Please, do not use that ugly hack anymore and do a proper if
                block.

                Or use Python 2.5 with the official ternary operator ;)

                Comment

                • Bruno Desthuilliers

                  #9
                  Re: Tertiary Operation

                  abcd wrote:
                  x = None
                  result = (x is None and "" or str(x))
                  You don't need the parenthesis.
                  print result, type(result)
                  >
                  ---------------
                  OUTPUT
                  ---------------
                  None <type 'str'>
                  >
                  >
                  y = 5
                  result = (y is 5 and "it's five" or "it's not five")
                  By all means *don't* use identity tests in such a context. Try with
                  100000 instead of 5:
                  >>x = 100000
                  >>x is 100000
                  False
                  >>>
                  print result
                  >
                  -------------
                  OUTPUT
                  -------------
                  it's five
                  >
                  ...what's wrong with the first operation I did with x? I was expecting
                  "result" to be an empty string, not the str value of None.
                  As other already pointed, an empty string (as well as an empty list,
                  tuple, dict, set IIRC, and zero int or float) evals to False in a
                  boolean context.

                  Python 2.5 has a ternary operator. If you need to deal with older Python
                  versions, another possible 'ternary op hack' is :

                  x = None
                  (str(x), "")[x is None]
                  =""
                  x = 42
                  (str(x), "")[x is None]
                  ="42"

                  This relies on the fact that False == 0 and True == 1.

                  NB : if you don't want to eval both terms before (which is how it should
                  be with a real ternanry operator), you can rewrite it like this:

                  result = (str, lambda obj:"")[x is None)(x)

                  But this begins to be unreadable enough to be replaced by a good old
                  if/else...

                  --
                  bruno desthuilliers
                  python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                  p in 'onurb@xiludom. gro'.split('@')])"

                  Comment

                  • Steven Bethard

                    #10
                    Re: Tertiary Operation

                    abcd wrote:
                    x = None
                    result = (x is None and "" or str(x))
                    print result, type(result)
                    >
                    ---------------
                    OUTPUT
                    ---------------
                    None <type 'str'>
                    >
                    >
                    [snip]
                    ...what's wrong with the first operation I did with x?
                    You weren't using Python 2.5:

                    Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit
                    (Intel)] on win32
                    Type "help", "copyright" , "credits" or "license" for more information.
                    >>x = None
                    >>'' if x is None else str(x)
                    ''
                    >>>
                    Time to upgrade. ;-)

                    Steve

                    Comment

                    • Fredrik Lundh

                      #11
                      Re: Tertiary Operation

                      Roy Smith wrote:
                      Why not just:
                      >
                      if x is None:
                      result = str(x)
                      else:
                      result = ""
                      >
                      It's a couple more lines of code, but it's obvious what it means.
                      and if you're doing this a few times, putting it in a function is even
                      better.

                      def tostring(obj):
                      if obj is None:
                      return ""
                      return str(obj)

                      print tostring(key)
                      print tostring(foo), tostring(bar)
                      file.write(tost ring(record[1]))

                      this also makes it easier to tweak things once you realize that not
                      everything should be passed through str():

                      def tostring(obj):
                      if obj is None:
                      return ""
                      if isinstance(obj, basestring):
                      return obj
                      return str(obj)

                      </F>

                      Comment

                      Working...