Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Alternative suggestion for conditional expressions (see PEP 308)

Reply
Thread Tools

Alternative suggestion for conditional expressions (see PEP 308)

 
 
neblackcat
Guest
Posts: n/a
 
      07-15-2004
Would anyone like to comment on the following idea?

I was just going to offer it as a new PEP until it was suggested that
I post it here for comment & consideration against PEP 308.

I'm far from being a "language internist" (on Python or anything else)
so go easy on me if this is stupid - it just seemed quite elegant to
me as a relative newbie in town

I also havent got a clue whether this would be easy or even possible
to implement even if it was deemed a reasonable idea.

-----------------------------------------------------------------------

Abstract

Implement C-like conditional expressions, but in a more
flexible and "Python-like" way.

Motivation

The lack of conditional expressions combined with the lack
of a 'switch' statement in Python tends to result in lots
of 'if'/'elif' lines which often arent needed and which make
code more verbose and sometimes (where there are a lot of
them) harder to follow and more prone to mistakes than it
needs to be.

This PEP attempts to address that by proposing a
'Pythonesque' conditional expressions language feature
which fits well with existing language features
and the way that conditional expressions are often
simulated in current Python code by using temporary
tuples, lists or dictionaries.


Rationale

It is currently possible to simulate conditional
expressions in Python using constructs with
temporary tuples/lists, such as:

sColorName = ("Black","White")[Color == COLOR_WHITE]

This works, but has two disadvantages:

i) it involves packing and unpacking of a 'temporary'
tuple, eg. ("Black","White") in the above, which
has performance implications

ii) this in turn means that *all* of the possible
final values have to be valid (not just the one
which will be actually selected), which is often
not the case in a more real-world example, eg:

r = (DEFAULT_RESULT, Database.Results[index])
[IsValid(index)]

In the above, 'Database.Results[index]' isn't
defined to be valid if the 'index' value isn't,
which means that this technique cant be used.

Specification

I therefore suggest a variation on the above
syntax such as:

sColorName = ?("Black","White")[Color == COLOR_WHITE]

where the '?' identifies the immediately following
tuple as a "conditional tuple" in which the tuple is
not actually fully evaluated/stored. Instead,
only the element specified by the immediately following
index expression is evaluated and must be valid.

This syntax could also apply to other sequence types,
for example dictionaries:

sColorName = ?{COLOR_RED:"Red",
COLOR_BLUE:"Blue",
COLOR_GREEN:"Green"}[ColorValue]

Again, the conditional sequence is not fully evaluated/stored,
so it doesnt matter if it is large and/or has members which
arent evaluated given an index value which doesnt actually
select them.

Obviously, the above are just simple examples.
 
Reply With Quote
 
 
 
 
Peter Hansen
Guest
Posts: n/a
 
      07-15-2004
neblackcat wrote:

> Would anyone like to comment on the following idea?
> Implement C-like conditional expressions, but in a more
> flexible and "Python-like" way.

[...]
> I therefore suggest a variation on the above
> syntax such as:
>
> sColorName = ?("Black","White")[Color == COLOR_WHITE]


Funky uses of punctuation are about as non-Pythonic as you
can get, so I doubt this idea would make it past the post...

-Peter
 
Reply With Quote
 
 
 
 
Larry Bates
Guest
Posts: n/a
 
      07-15-2004
Seems that every one of the examples can be done
with a dictionary.

sColorName = ("Black","White")[Color == COLOR_WHITE]

use dictionary lookup:

colorNameDict={COLOR_WHITE:"White", COLOR_BLACK: "BLACK"}
sColorName=colorNameDict[Color]


and

sColorName = ?{COLOR_RED:"Red",
COLOR_BLUE:"Blue",
COLOR_GREEN:"Green"}[ColorValue]


can be done as:

colorNameDict={COLOR_RED:"Red",
COLOR_BLUE:"Blue",
COLOR_GREEN:"Green"}

sColorName=colorNameDict[ColorValue

you can also handle the "Default/undefined" case as:

colorNameDict={COLOR_RED:"Red",
COLOR_BLUE:"Blue",
COLOR_GREEN:"Green"}

sColorname=ColorNameDict.get(ColorValue, defaultvalue)

or as I often do:

colorNameDict={COLOR_RED:"Red",
COLOR_BLUE:"Blue",
COLOR_GREEN:"Green",
'unknown': 'Unknown'}

sColorname=colorNameDict.get(ColorValue, colorNameDict['unknown'])

Since these dictionaries should be defined once and never
inside a loop, I don't believe that performance is an issue.

You can also simulate a switch statement as follows:

def foo(args):
print "in foo"

def bar(args):
print "in bar"

def hee(args):
print "in hee"

def unknown(args):
print "in unknown"

switchDict={'one': foo, 'two': bar, 'three': hee,
'default': unknown}

switchvalue='one'
switchFunction=switchDict.get(switchvalue, switchvalue['default'])
switchFunction(args)

Again you get excellent performance because dictionary lookups
are blazingly fast. switchDict is only evaluated a single time
(or should be) and is easily extendable by simply adding more
switch values as keys.

Larry Bates
Syscon, Inc.

"neblackcat" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...
> Would anyone like to comment on the following idea?
>
> I was just going to offer it as a new PEP until it was suggested that
> I post it here for comment & consideration against PEP 308.
>
> I'm far from being a "language internist" (on Python or anything else)
> so go easy on me if this is stupid - it just seemed quite elegant to
> me as a relative newbie in town
>
> I also havent got a clue whether this would be easy or even possible
> to implement even if it was deemed a reasonable idea.
>
> -----------------------------------------------------------------------
>
> Abstract
>
> Implement C-like conditional expressions, but in a more
> flexible and "Python-like" way.
>
> Motivation
>
> The lack of conditional expressions combined with the lack
> of a 'switch' statement in Python tends to result in lots
> of 'if'/'elif' lines which often arent needed and which make
> code more verbose and sometimes (where there are a lot of
> them) harder to follow and more prone to mistakes than it
> needs to be.
>
> This PEP attempts to address that by proposing a
> 'Pythonesque' conditional expressions language feature
> which fits well with existing language features
> and the way that conditional expressions are often
> simulated in current Python code by using temporary
> tuples, lists or dictionaries.
>
>
> Rationale
>
> It is currently possible to simulate conditional
> expressions in Python using constructs with
> temporary tuples/lists, such as:
>
> sColorName = ("Black","White")[Color == COLOR_WHITE]
>
> This works, but has two disadvantages:
>
> i) it involves packing and unpacking of a 'temporary'
> tuple, eg. ("Black","White") in the above, which
> has performance implications
>
> ii) this in turn means that *all* of the possible
> final values have to be valid (not just the one
> which will be actually selected), which is often
> not the case in a more real-world example, eg:
>
> r = (DEFAULT_RESULT, Database.Results[index])
> [IsValid(index)]
>
> In the above, 'Database.Results[index]' isn't
> defined to be valid if the 'index' value isn't,
> which means that this technique cant be used.
>
> Specification
>
> I therefore suggest a variation on the above
> syntax such as:
>
> sColorName = ?("Black","White")[Color == COLOR_WHITE]
>
> where the '?' identifies the immediately following
> tuple as a "conditional tuple" in which the tuple is
> not actually fully evaluated/stored. Instead,
> only the element specified by the immediately following
> index expression is evaluated and must be valid.
>
> This syntax could also apply to other sequence types,
> for example dictionaries:
>
> sColorName = ?{COLOR_RED:"Red",
> COLOR_BLUE:"Blue",
> COLOR_GREEN:"Green"}[ColorValue]
>
> Again, the conditional sequence is not fully evaluated/stored,
> so it doesnt matter if it is large and/or has members which
> arent evaluated given an index value which doesnt actually
> select them.
>
> Obviously, the above are just simple examples.



 
Reply With Quote
 
Jeff Shannon
Guest
Posts: n/a
 
      07-15-2004
Larry Bates wrote:

>Seems that every one of the examples can be done
>with a dictionary.
>
>


While that may be true of the examples given here, it's not true of all
cases. The one possible real advantage of a conditional expression, as
I see it, is shortcutting. In cases where the conditionally-executed
code has side effects, it can be important to ensure that *only* one
branch is evaluated; creating an actual dictionary (whether permanent or
temporary) will execute *all* branches. For example, using neblackcat's
proposed syntax (even though I'm *not* fond of it):

nextline = ?(FileOne.readline(), FileTwo.readline())[whichfile]

In this case, since reading a line from a file advances the filepointer,
executing both will result in a line being "lost" from the non-selected
file. (I realize that in this specific example, one could use the
conditional to select a file object and call readline() on the result of
the conditional; I could also construct examples in which entirely
different operations-with-side-effects are performed on each branch so
that refactoring in that way isn't practical, or one branch is a string
literal and the other has some side-effect, or whatever.)

Note that, while I do think it's important to be aware of this
distinction, I'm not advocating the proposed syntax (I'm rather leery of
using punctuation like that, as Peter Hansen mentions) or even
necessarily advocating for a conditional expression at all. I remain
unconvinced of the need for an expression to do what can already be done
with statements -- a conditional expression may be more concise, but
conciseness more often hampers readability than helps it, and
readability is very important. I've heard the arguments that using a
multiline if/else construct in order to set up parameters for a function
call is ugly, but I personally find that to be no worse than the
ugliness of conditional expressions...

Jeff Shannon
Technician/Programmer
Credit International



 
Reply With Quote
 
Phil Frost
Guest
Posts: n/a
 
      07-15-2004
On Thu, Jul 15, 2004 at 12:17:08PM -0700, Jeff Shannon wrote:
> Larry Bates wrote:
>
> >Seems that every one of the examples can be done
> >with a dictionary.

>
> While that may be true of the examples given here, it's not true of all
> cases. The one possible real advantage of a conditional expression, as
> I see it, is shortcutting. In cases where the conditionally-executed
> code has side effects, it can be important to ensure that *only* one
> branch is evaluated; creating an actual dictionary (whether permanent or
> temporary) will execute *all* branches. For example, using neblackcat's
> proposed syntax (even though I'm *not* fond of it):
>
> nextline = ?(FileOne.readline(), FileTwo.readline())[whichfile]
>
> ...


Evaluation of the expressions could be deferred by using callables, like
so:

next = (lambda: fileone.readline(), lambda filetwo.readline())[which]()

Or since in this example both sides of the tuple are already callables:

next = (fileone.readline, filetwo.readline)[which]()

But then really, is writing:

if which: next=fileone.readline()
else: next=filetwo.readline()

all that bad?
 
Reply With Quote
 
Colin J. Williams
Guest
Posts: n/a
 
      07-16-2004
I was inclined to support PEP 308, but now wonder whether it's really
needed.

sColorName = ("Black","White")[Color == COLOR_WHITE]

Could be:

sColorName = Color == COLOR_WHITE and "Black" or "White"

which takes avantantage of the short circuit evaluation

sColorName= color == colorwhite and "white" or garbage

This gives the correct result when only the first case needs to be
evalutated.

Colin W.

neblackcat wrote:
> Would anyone like to comment on the following idea?
>
> I was just going to offer it as a new PEP until it was suggested that
> I post it here for comment & consideration against PEP 308.
>
> I'm far from being a "language internist" (on Python or anything else)
> so go easy on me if this is stupid - it just seemed quite elegant to
> me as a relative newbie in town
>
> I also havent got a clue whether this would be easy or even possible
> to implement even if it was deemed a reasonable idea.
>
> -----------------------------------------------------------------------
>
> Abstract
>
> Implement C-like conditional expressions, but in a more
> flexible and "Python-like" way.
>
> Motivation
>
> The lack of conditional expressions combined with the lack
> of a 'switch' statement in Python tends to result in lots
> of 'if'/'elif' lines which often arent needed and which make
> code more verbose and sometimes (where there are a lot of
> them) harder to follow and more prone to mistakes than it
> needs to be.
>
> This PEP attempts to address that by proposing a
> 'Pythonesque' conditional expressions language feature
> which fits well with existing language features
> and the way that conditional expressions are often
> simulated in current Python code by using temporary
> tuples, lists or dictionaries.
>
>
> Rationale
>
> It is currently possible to simulate conditional
> expressions in Python using constructs with
> temporary tuples/lists, such as:
>
> sColorName = ("Black","White")[Color == COLOR_WHITE]
>
> This works, but has two disadvantages:
>
> i) it involves packing and unpacking of a 'temporary'
> tuple, eg. ("Black","White") in the above, which
> has performance implications
>
> ii) this in turn means that *all* of the possible
> final values have to be valid (not just the one
> which will be actually selected), which is often
> not the case in a more real-world example, eg:
>
> r = (DEFAULT_RESULT, Database.Results[index])
> [IsValid(index)]
>
> In the above, 'Database.Results[index]' isn't
> defined to be valid if the 'index' value isn't,
> which means that this technique cant be used.
>
> Specification
>
> I therefore suggest a variation on the above
> syntax such as:
>
> sColorName = ?("Black","White")[Color == COLOR_WHITE]
>
> where the '?' identifies the immediately following
> tuple as a "conditional tuple" in which the tuple is
> not actually fully evaluated/stored. Instead,
> only the element specified by the immediately following
> index expression is evaluated and must be valid.
>
> This syntax could also apply to other sequence types,
> for example dictionaries:
>
> sColorName = ?{COLOR_RED:"Red",
> COLOR_BLUE:"Blue",
> COLOR_GREEN:"Green"}[ColorValue]
>
> Again, the conditional sequence is not fully evaluated/stored,
> so it doesnt matter if it is large and/or has members which
> arent evaluated given an index value which doesnt actually
> select them.
>
> Obviously, the above are just simple examples.


 
Reply With Quote
 
Mark 'Kamikaze' Hughes
Guest
Posts: n/a
 
      07-16-2004
Colin J. Williams <(E-Mail Removed)>
wrote on Fri, 16 Jul 2004 09:49:22 -0400:
> I was inclined to support PEP 308, but now wonder whether it's really
> needed.
> sColorName = ("Black","White")[Color == COLOR_WHITE]
> Could be:
> sColorName = Color == COLOR_WHITE and "Black" or "White"
> which takes avantantage of the short circuit evaluation
> sColorName= color == colorwhite and "white" or garbage
> This gives the correct result when only the first case needs to be
> evalutated.


This works only as long as the results of the (true, false) choices
both evaluate true:

>>> def foo():

.... print "eval foo"
.... return "foo"
....
>>> def bar():

.... print "eval bar"
.... return "bar"
....
>>> False and foo() or bar()

eval bar
'bar'
>>> True and foo() or bar()

eval foo
'foo'

Looks good, right?

>>> def foo():

.... print "eval foo"
.... return ""
....
>>> False and foo() or bar()

eval bar
'bar'
>>> True and foo() or bar()

eval foo
eval bar
'bar'

Alas. Not only does it evaluate both, causing who-knows-what side
effects, it returns the wrong answer. Your Python nuclear missile
launch program goes out of control. All die. O the embarassment.

This is why we do actually need a ternary. It's not that the language
lacks tools for choosing now, but that this behavior is so very easy to
get wrong, and leads to very subtle bugs.

The PEP 308 vote showed that at least 84% of the Python users wanted a
ternary. A second vote between the four major choices would have
obviously ended us up with the (if <cond1>: <expr1> elif <cond2>:
<expr2> ... else: <exprN>) form, which is about as Pythonically
unambiguous as you can get.

At the time, my opinion was that I didn't need a ternary often enough
to care. Sometimes I want to modify some math depending on a boolean,
and in that case I can just treat it as 0 or 1:

>>> 5 + 3 * True

8

And the rest of the time, it's easy (if tedious) to just write:

>>> if True: a=foo()

.... else: a=bar()
....
eval foo
>>> a

''

However, the ease of doing the and...or and ()[] versions wrong, and
how unbelievably ugly the latter is, have changed my mind from "this is
not important" to "this is something Python really does need, after
all".

--
<a href="http://kuoi.asui.uidaho.edu/~kamikaze/"> Mark Hughes </a>
"The void breathed hard on my heart, turning its illusions to ice, shattering
them. Was reborn, then, free to scrawl own design on this morally blank
world. Was Rorschach." --Alan Moore, _Watchmen #6_, "The Abyss Gazes Also"
 
Reply With Quote
 
=?iso-8859-15?Q?Pierre-Fr=E9d=E9ric_Caillaud?=
Guest
Posts: n/a
 
      07-19-2004

Flame suit on.

- add a switch-case statement :
I do miss a switch-case in Python.
The interpreter can't really optimize if/elif as a dictionary lookup,
because what if there is a AND or OR clause, or if the object has defined
a __cmp__ method with side effects ? This would be pervert...

switch color:
case 1:
name = 'red'
case 2:
name = 'blue'
case 3:
case 4:
name = 'colorblind'

Could use a 'break' (like in C) or not (cleaner).

- add a switch-case statement which can return a value.
Problem : you need a new keyword for that, which is a bad thing... and it
starts to look like lisp...

I think the ternary operator is a half-baked solution to a more general
problem ; it is useful as a little shortcut like " x ? 'Yes' : 'No' but
doing more with it leads to obfuscation.

Still, something lacks in Python... just like the break-n-levels.

 
Reply With Quote
 
Mark 'Kamikaze' Hughes
Guest
Posts: n/a
 
      07-20-2004
Pierre-Frédéric Caillaud <(E-Mail Removed)>
wrote on Mon, 19 Jul 2004 19:31:07 +0200:
> Flame suit on.
> - add a switch-case statement :
> I do miss a switch-case in Python.
> The interpreter can't really optimize if/elif as a dictionary lookup,
> because what if there is a AND or OR clause, or if the object has defined
> a __cmp__ method with side effects ? This would be pervert...
> switch color:
> case 1:
> name = 'red'
> case 2:
> name = 'blue'
> case 3:
> case 4:
> name = 'colorblind'
> Could use a 'break' (like in C) or not (cleaner).
> - add a switch-case statement which can return a value.
> Problem : you need a new keyword for that, which is a bad thing... and it
> starts to look like lisp...


Simpler version that already works:
colornames = {
1: "red",
2: "blue",
}
print colornames.get(color, "colorblind")

> I think the ternary operator is a half-baked solution to a more general
> problem ; it is useful as a little shortcut like " x ? 'Yes' : 'No' but
> doing more with it leads to obfuscation.


It's more for selecting between function calls than for constants. A
common idiom with a ternary in Java is:
value = test == null ? null : test.something();

That doesn't happen as often in Python, but choosing between different
methods depending on a flag happens more often.

> Still, something lacks in Python... just like the break-n-levels.


At least there's a consistent and easy way to do that. Use
exceptions, or extract your inner loops into a method, and return when
you want to "break out".

--
<a href="http://kuoi.asui.uidaho.edu/~kamikaze/"> Mark Hughes </a>
"Spontaneous deliquescence is now a protected condition under the Americans with
Disabilities Act." -John J. Reilly, "Cthuluism and the Cold War"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
PEP 8 exegetics: conditional imports? kj Python 8 08-08-2009 03:29 AM
About Rational Number (PEP 239/PEP 240) Lie Python 25 12-18-2007 06:13 AM
Conditional expressions - PEP 308 Colin J. Williams Python 4 01-31-2007 04:50 PM
[Info] PEP 308 accepted - new conditional expressions Reinhold Birkenfeld Python 62 10-16-2005 06:27 PM
PEP for new modules (I read PEP 2) Christoph Becker-Freyseng Python 3 01-16-2004 04:26 PM



Advertisments