[Python-Dev] Adding a conditional expression in Py3.0

Steve Holden steve at holdenweb.com
Thu Sep 29 17:54:46 CEST 2005


Guido van Rossum wrote:
> On 9/29/05, Raymond Hettinger <raymond.hettinger at verizon.net> wrote:
> 
>>FWIW, I scanned the standard library for all the and/or pairings where a
>>conditional expression was applicable.  This sampling can serve as a
>>reference for what "typical" uses would look like in real Python code as
>>created by a number of different authors.
>>
>>It only takes about five minutes to try out a given syntax proposal on
>>all the fragments listed below.  That short exercise provides an
>>excellent insight into the look and feel of each proposal in real world
>>code.
> 
> 
> I did this for my favorite proposal, and ended up with the list shown
> further down below.
> 
> I think they all looks great!
> 
The fact that so few were found in whole of the standard library does 
put the use case into question, though, no? Though I am sure more could 
be found with a more thorough scan.

> The only problem is that it's not easy to come up with a regex-based
> way to transform
> 
>     C and X or Y
> 
> into
> 
>     X if C else Y
> 
> because it's hard to determine where C starts. So I recommend that
> people leave existing and/or code alone but start writing if/else
> expressions in new code only. After all there's nothing wrong with
> and/or.
> 
> cgitb.py:         file = os.path.abspath(file) if file else '?'
> cgitb.py:         formatter = html if self.format == "html" else text
> compileal1.py:                 cfile = fullname + ('c' if __debug__ else 'o')
> csv.py:                            a if (quotes[a] > quotes[b]) else
> b, quotes.keys())
> csv.py:                            a if (delims[a] > delims[b]) else
> b, delims.keys())
> csv.py:                     modes[char] = reduce(lambda a, b: a if
> a[1] > b[1] else b,
> DocXMLRPCServer.py:         anchor = (cl.__name__ if cl else '') + '-' + name
> fileinput.py:                                    "*" if isfirstline()
> else "", line)
> formatter.py:             self.writer.send_paragraph((1) if blankline else 0)
> gettext.py:         __builtin__.__dict__['_'] = self.ugettext if
> unicode else self.gettext
> imaplib.py:             l = map(lambda x:'%s: "%s"' % (x[0], '"
> "'.join(x[1]) if x[1][0] else ''), l)
> imputil.py: _suffix_char = 'c' if __debug__ else 'o'
> keyword.py:     iptfile = args[0] if args else "Python/graminit.c"
> pickle.py:             self.write(NEWTRUE if obj else NEWFALSE)
> pickle.py:             self.write(TRUE if obj else FALSE)
> pickletools.py:                                  "<unknown>" if pos is
> None else pos,
> py_compile.py:         cfile = file + ('c' if __debug__ else 'o')
> pydoc.py:     return re.sub('^ *\n', '', rstrip(result)) if result else ''
> pydoc.py:         anchor = (cl.__name__ if cl else '') + '-' + name
> pydoc.py:         lhs = '<strong>%s</strong> = ' % name if name else ''
> pydoc.py:         contents = [doc + '\n'] if doc else []
> pydoc.py:             line = (name + ' = ' if name else '') + repr
> pydoc.py:         line = (self.bold(name) + ' = ' if name else '') + repr
> pydoc.py:             host = '127.0.0.1' if (sys.platform == 'mac')
> else 'localhost'
> pydoc.py:             font = ('helvetica', 8 if sys.platform == 'win32' else 10)
> robotp~1.py:         return (self."Allow" if allowance else
> "Disallow")+": "+self.path
> telnet~1.py:                             'DO' if cmd == DO else
> 'DONT', ord(opt))
> telnet~1.py:                             'WILL' if cmd == WILL else
> 'WONT', ord(opt))
> thread~1.py:                    "s" if n!=1 else "")
> token.py:     inFileName = args[0] if args else "Include/token.h"
> tokenize.py:                     yield (parenlev > NL if 0 else NEWLINE,
> unittest.py:         return doc.split("\n")[0].strip() if doc else None
> unittest.py:         return doc.split("\n")[0].strip() if doc else None
> unittest.py:                             (run, run != "s" if 1 else
> "", timeTaken))
> urllib.py:             safe_map[c] = c if (c in safe) else ('%%%02X' % i)
> urllib2.py:             type = 'I' if file else 'D'
> xdrlib.py:                 print 'succeed' if pred(x) else 'failed', ':', x
> xmlrpclib.py:             write("1" if value else "0")
> 

Having though about it more closely, the reason I believe it might 
confuse newbies is because until the "else" comes along the construct 
can easily be read as a statement with a conditional suffix, and it's 
only after you read the "else" it becomes obvious that it's the 
expression that's conditional.

I realise that this reading will become habitual once this proposal is 
put into the language, but I do think this will be a source of confusion 
to newcomers (who should anyway be steered away from all the magic of 
ternary expressions, list comprehensions, generator expressions and the 
like.

I would argue for mandatory parentheses around the expression, leaving 
room later (probably after Guido is no longer around to be sick at the 
site of it) for:

def f(condition):
     return something if condition # no else!
     return somethingElse

not-expecting-this-to-fly-ly y'rs  - steve
-- 
Steve Holden       +44 150 684 7255  +1 800 494 3119
Holden Web LLC                     www.holdenweb.com
PyCon TX 2006                          www.pycon.org



More information about the Python-Dev mailing list