443,846 Members | 1,836 Online
Need help? Post your question and get tips & solutions from a community of 443,846 IT Pros & Developers. It's quick & easy.

# Tertiary Operation

 P: n/a 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. Oct 17 '06 #1
10 Replies

 P: n/a "abcd" 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 Oct 17 '06 #2

 P: n/a 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 Oct 17 '06 #3

 P: n/a 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 Oct 17 '06 #4

 P: n/a 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. Oct 17 '06 #5

 P: n/a 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. Oct 17 '06 #6

 P: n/a In article <11**********************@i3g2000cwc.googlegroups. com>, "abcd"

 P: n/a 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 "" 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 :

 P: n/a 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 100000 instead of 5: >>x = 100000x 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 'o****@xiludom.gro'.split('@')])" Oct 17 '06 #9

 P: n/a 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 Oct 17 '06 #10

 P: n/a 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) Oct 17 '06 #11

### This discussion thread is closed

Replies have been disabled for this discussion.