Re: Tertiary Operation

2006-10-17 Thread Fredrik Lundh
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(tostring(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)



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Steven Bethard
abcd wrote:
> x = None
> result = (x is None and "" or str(x))
> print result, type(result)
> 
> ---
> OUTPUT
> ---
> None 
> 
> 
[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
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Bruno Desthuilliers
abcd wrote:
> x = None
> result = (x is None and "" or str(x))

You don't need the parenthesis.

> print result, type(result)
> 
> ---
> OUTPUT
> ---
> None 
> 
> 
> 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
10 instead of 5:
>>> x = 10
>>> x is 10
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 '[EMAIL PROTECTED]'.split('@')])"
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Christophe
abcd a écrit :
> x = None
> result = (x is None and "" or str(x))
> 
> print result, type(result)
> 
> ---
> OUTPUT
> ---
> None 
> 
> 
> 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 " and  or " 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 :  must 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 ;)

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Roy Smith
In article <[EMAIL PROTECTED]>,
 "abcd" <[EMAIL PROTECTED]> wrote:

> 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.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Steven D'Aprano
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.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Carsten Haese
On Tue, 2006-10-17 at 09:48, Tim Chase wrote:
> [...]
> Either of the following should suffice:
> 
>   # return a non-empty string
>   x is None and "None" or str(x)

This one can be "optimized" to just str(x) since str(None)=="None".

>[...]
> 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).

Python 2.5 does already.

>   My understanding is that one common 
> solution is something like
> 
>   {True: "", False: str(x)}[x is None]

As Fredrik pointed out in not so many words, this is not a good
solution. Besides being ugly, the major problem with this solution is
that both branches are evaluated regardless of the outcome of the
condition. This is not good if the expression is unsafe to calculate
under the wrong condition, or if the expressions are expensive to
calculate, or if the expressions have side effects.

The "condition and result1 or result2" hack at least prevents the
evaluation of the non-applicable expression due to the short-circuiting
nature of the "and" and "or" operators.

-Carsten


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Fredrik Lundh
Tim Chase wrote:

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

first the localtime/mktime roundtrip with a simulated cast, and now this?  in 
less
than one hour?  solar flares?

 



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread abcd
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.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Carsten Haese
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 

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


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Tim Chase
> x = None
> result = (x is None and "" or str(x))
> 
> print result, type(result)
> 
> ---
> OUTPUT
> ---
> None 
> 
> 
> 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



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Tertiary Operation

2006-10-17 Thread Richard Brodie

"abcd" <[EMAIL PROTECTED]> wrote in message 
news:[EMAIL PROTECTED]

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

http://docs.python.org/whatsnew/pep-308.html 


-- 
http://mail.python.org/mailman/listinfo/python-list


Tertiary Operation

2006-10-17 Thread abcd
x = None
result = (x is None and "" or str(x))

print result, type(result)

---
OUTPUT
---
None 


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.

-- 
http://mail.python.org/mailman/listinfo/python-list