469,916 Members | 2,115 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,916 developers. It's quick & easy.

the PHP ternary operator equivalent on Python

Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?

Thanks

Daniel

Nov 22 '05 #1
48 2413
On 18 Nov 2005 10:53:04 -0800, Daniel Crespo <dc*****@gmail.com> wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...


Wait for Python 2.5 - <http://www.python.org/peps/pep-0308.html>.

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Nov 22 '05 #2
On 18 Nov 2005 10:53:04 -0800, Daniel Crespo <dc*****@gmail.com> wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...


Wait for Python 2.5 - <http://www.python.org/peps/pep-0308.html>.

--
Cheers,
Simon B,
si***@brunningonline.net,
http://www.brunningonline.net/simon/blog/
Nov 22 '05 #3
Daniel Crespo wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}


Well, in your example the '>' operator already returns a boolean value
so you can just use it directly. Hoewver, I agree that there are
situations in which a ternary operator would be nice. Unfortunately,
Python doesn't support this directly; the closest approximation I've
found is:
(value_if_false, value_if_true)[boolean_value]
This exploits the fact that False and True are converted to integers as
zero and one, respectively. The downside is that it's really ugly.
Also, it doesn't use minimal evaluation; in other words, if you try an
expression like:
(None, func())[callable(func)]
You might think this would return the value of func() if it's callable,
and None otherwise. Unfortunately, func() is evaluated no matter what,
even if the condition is false.

Of course, you can always get around this by doing really cryptic stuff
with lambdas:
(lambda: None, lambda: func())[callable(func)]()


.... but by that point, you're better off just using an if/then/else.

-- David

Nov 22 '05 #4
Daniel Crespo wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}


Well, in your example the '>' operator already returns a boolean value
so you can just use it directly. Hoewver, I agree that there are
situations in which a ternary operator would be nice. Unfortunately,
Python doesn't support this directly; the closest approximation I've
found is:
(value_if_false, value_if_true)[boolean_value]
This exploits the fact that False and True are converted to integers as
zero and one, respectively. The downside is that it's really ugly.
Also, it doesn't use minimal evaluation; in other words, if you try an
expression like:
(None, func())[callable(func)]
You might think this would return the value of func() if it's callable,
and None otherwise. Unfortunately, func() is evaluated no matter what,
even if the condition is false.

Of course, you can always get around this by doing really cryptic stuff
with lambdas:
(lambda: None, lambda: func())[callable(func)]()


.... but by that point, you're better off just using an if/then/else.

-- David

Nov 22 '05 #5
"Daniel Crespo" <dc*****@gmail.com> writes:
Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?


Lots of ways, depending on your exact needs. What's best for what you
suggest is "a = {Huge : (False, True)[quantity > 90]}". Googling the
python newsgroup will turn up lots of others.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 22 '05 #6
"Daniel Crespo" <dc*****@gmail.com> writes:
Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?


Lots of ways, depending on your exact needs. What's best for what you
suggest is "a = {Huge : (False, True)[quantity > 90]}". Googling the
python newsgroup will turn up lots of others.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Nov 22 '05 #7

Mike Meyer wrote:
"Daniel Crespo" <dc*****@gmail.com> writes:
Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?


Lots of ways, depending on your exact needs. What's best for what you
suggest is "a = {Huge : (False, True)[quantity > 90]}". Googling the


http://www.python.org/doc/faq/progra...rnary-operator

Nov 22 '05 #8

Mike Meyer wrote:
"Daniel Crespo" <dc*****@gmail.com> writes:
Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?


Lots of ways, depending on your exact needs. What's best for what you
suggest is "a = {Huge : (False, True)[quantity > 90]}". Googling the


http://www.python.org/doc/faq/progra...rnary-operator

Nov 22 '05 #9
Oh... Well, thanks for that information.

I'll do this then:

def TernaryOperation(condition,true_part,false_part):
if condition:
return True-part
else:
return False-part

a = {'Huge': TernaryOperation(quantity>90,True,False)}

Thank you

Nov 22 '05 #10
Oh... Well, thanks for that information.

I'll do this then:

def TernaryOperation(condition,true_part,false_part):
if condition:
return True-part
else:
return False-part

a = {'Huge': TernaryOperation(quantity>90,True,False)}

Thank you

Nov 22 '05 #11
Daniel Crespo wrote:
Oh... Well, thanks for that information.

I'll do this then:

def TernaryOperation(condition,true_part,false_part):
if condition:
return True-part
else:
return False-part

a = {'Huge': TernaryOperation(quantity>90,True,False)}


By the time it compiles it will do the same as

a = {"Huge": quantity>90}

Consider describing your actual problem and keep in mind that the "ternary
operator" is a means, not an end.

Peter

Nov 22 '05 #12
Daniel Crespo wrote:
Oh... Well, thanks for that information.

I'll do this then:

def TernaryOperation(condition,true_part,false_part):
if condition:
return True-part
else:
return False-part

a = {'Huge': TernaryOperation(quantity>90,True,False)}


By the time it compiles it will do the same as

a = {"Huge": quantity>90}

Consider describing your actual problem and keep in mind that the "ternary
operator" is a means, not an end.

Peter

Nov 22 '05 #13
On 2005-11-18, Daniel Crespo <dc*****@gmail.com> wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...


The _PHP_ ternary operator (x?y:z)!

Kids these days!

--
Grant Edwards grante Yow! It's so OBVIOUS!!
at
visi.com
Nov 22 '05 #14
On 2005-11-18, Daniel Crespo <dc*****@gmail.com> wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...


The _PHP_ ternary operator (x?y:z)!

Kids these days!

--
Grant Edwards grante Yow! It's so OBVIOUS!!
at
visi.com
Nov 22 '05 #15
Hi Peter,

Expand your mind.

a = {'whatever': TernaryOperation(quantity>90,"It is very huge","The
value is correct")}

;-)

thanks for your advice anyway

Daniel

Nov 22 '05 #16
Hi Peter,

Expand your mind.

a = {'whatever': TernaryOperation(quantity>90,"It is very huge","The
value is correct")}

;-)

thanks for your advice anyway

Daniel

Nov 22 '05 #17
Another way to simulate the ternary operator is this:

a = (quantity > 90 and "It is very huge") or "The value is correct"

You have to be careful of semantics of 'and' and 'or'. But in this case
I wonder why you don't just test whether quantity is greater than 90
and assign the corresponding value to a, e.g., :

if quantity > 90:
a = "It is huge"
else:
a = "Time for tea."
Clarity is a virtue, and simulating ternary operator doesn't always
serve that end.

Nov 22 '05 #18
Another way to simulate the ternary operator is this:

a = (quantity > 90 and "It is very huge") or "The value is correct"

You have to be careful of semantics of 'and' and 'or'. But in this case
I wonder why you don't just test whether quantity is greater than 90
and assign the corresponding value to a, e.g., :

if quantity > 90:
a = "It is huge"
else:
a = "Time for tea."
Clarity is a virtue, and simulating ternary operator doesn't always
serve that end.

Nov 22 '05 #19
The cleanest(IMO) is this :

a = (predicate and [if_true_expr] or [if_false_expr])[0]

This would give you the necessary "short circuit" behaviour no matter
what.

a = predicate and if_true_expr or if_false_expr

works most of the time but should if_true_expr turns out to be 0 or
something like that(python False equvialent), the if_false_expr will
still be executed, that becomes a logic error. an example :
a = int_str is None and None or int(int_str)
a = [if_false_expr, if_true_expr][predicate]

This doesn't have the "short circuit" feature and the order is
reversed(harder to read for people familiar with ternary operator).
Cannot be used in some case. like this :

a = [0, int(int_str)][int_str is not None]

here int(int_str) may cause exception if None is a valid value.

The lambda form suggested by others is another variant of the first one
above where you get the short circuit feature but too complex to read.

I don't understand why people are so aganst ternary operator. It is a
must for list comprehension/generator expression(and I believe the
reason it has finally been approved), if/else block or try/except just
don't work in these situations.

Daniel Crespo wrote:
Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?

Thanks

Daniel


Nov 22 '05 #20
The cleanest(IMO) is this :

a = (predicate and [if_true_expr] or [if_false_expr])[0]

This would give you the necessary "short circuit" behaviour no matter
what.

a = predicate and if_true_expr or if_false_expr

works most of the time but should if_true_expr turns out to be 0 or
something like that(python False equvialent), the if_false_expr will
still be executed, that becomes a logic error. an example :
a = int_str is None and None or int(int_str)
a = [if_false_expr, if_true_expr][predicate]

This doesn't have the "short circuit" feature and the order is
reversed(harder to read for people familiar with ternary operator).
Cannot be used in some case. like this :

a = [0, int(int_str)][int_str is not None]

here int(int_str) may cause exception if None is a valid value.

The lambda form suggested by others is another variant of the first one
above where you get the short circuit feature but too complex to read.

I don't understand why people are so aganst ternary operator. It is a
must for list comprehension/generator expression(and I believe the
reason it has finally been approved), if/else block or try/except just
don't work in these situations.

Daniel Crespo wrote:
Hi!

I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}

Any suggestions?

Thanks

Daniel


Nov 22 '05 #21
On Fri, 18 Nov 2005 11:17:17 -0800, David Wahler wrote:
Daniel Crespo wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}


Well, in your example the '>' operator already returns a boolean value
so you can just use it directly. Hoewver, I agree that there are
situations in which a ternary operator would be nice. Unfortunately,
Python doesn't support this directly; the closest approximation I've
found is:
(value_if_false, value_if_true)[boolean_value]


Which doesn't short-circuit: both value_if_false and value_if_true are
evaluated.

WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.


--
Steven.

Nov 22 '05 #22
On Fri, 18 Nov 2005 11:17:17 -0800, David Wahler wrote:
Daniel Crespo wrote:
I would like to know how can I do the PHP ternary operator/statement
(... ? ... : ...) in Python...

I want to something like:

a = {'Huge': (quantity>90) ? True : False}


Well, in your example the '>' operator already returns a boolean value
so you can just use it directly. Hoewver, I agree that there are
situations in which a ternary operator would be nice. Unfortunately,
Python doesn't support this directly; the closest approximation I've
found is:
(value_if_false, value_if_true)[boolean_value]


Which doesn't short-circuit: both value_if_false and value_if_true are
evaluated.

WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.


--
Steven.

Nov 22 '05 #23

Steven D'Aprano wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.

How do you put this block into list comprehension or generator
expression ? Why the obsession of these block style ?

Nov 22 '05 #24

Steven D'Aprano wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.

How do you put this block into list comprehension or generator
expression ? Why the obsession of these block style ?

Nov 22 '05 #25
In article <11*********************@g47g2000cwa.googlegroups. com>,
"bo****@gmail.com" <bo****@gmail.com> wrote:
Steven D'Aprano wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.

How do you put this block into list comprehension or generator
expression ? Why the obsession of these block style ?


I think the list comprehensions are going to be the death of readable
python programs.
Nov 22 '05 #26
In article <11*********************@g47g2000cwa.googlegroups. com>,
"bo****@gmail.com" <bo****@gmail.com> wrote:
Steven D'Aprano wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.

How do you put this block into list comprehension or generator
expression ? Why the obsession of these block style ?


I think the list comprehensions are going to be the death of readable
python programs.
Nov 22 '05 #27

Roy Smith wrote:
I think the list comprehensions are going to be the death of readable
python programs.

Could be, but seems that someone in charge of the language wants
readable python programs to die then as if list comprehension is not
enough, there comes generator expression and now the formal acceptance
of ternary operator.

Nov 22 '05 #28

Roy Smith wrote:
I think the list comprehensions are going to be the death of readable
python programs.

Could be, but seems that someone in charge of the language wants
readable python programs to die then as if list comprehension is not
enough, there comes generator expression and now the formal acceptance
of ternary operator.

Nov 22 '05 #29
On Fri, 18 Nov 2005 21:05:50 -0800, bo****@gmail.com wrote:

Steven D'Aprano wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.

How do you put this block into list comprehension or generator
expression ? Why the obsession of these block style ?


Why do you assume that everything you need for your list comprehension has
to go into a single line? Chances are your list comp already calls
functions, so just create one more for it to use.
py> def describe(cond):
.... if cond:
.... return "odd"
.... else:
.... return "even"
....
py> L = [describe(n % 2) for n in range(8)]
py> L
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

One major advantage is that this makes it easier to test your function
describe() in isolation, always a good thing.

Another advantage is that the idiom "call a function" is extensible to
more complex problems:

def describe(n):
if n < 0:
return "negative " + describe(-n)
elif n == 0:
return "zero"
elif n % 2:
return "odd"
else:
return "even"

L = [describe(n) for n in range(8)]

if much easier to understand and follow than using ternary expressions:

# obviously untested
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]

Yes, I've seen ternary expressions nested three and even four deep.

I find it fascinating to read Guido's reasoning for introducing a ternary
statement. From the PEP here http://www.python.org/peps/pep-0308.html he
links to this comment of his:

[quote]
I think Raymond's example is more properly considered an argument for
adding a conditional expression than for removing the current behavior of
the and/or shortcut operators; had we had a conditional expression, he
wouldn't have tried to use the "x and y or z" syntax that bit him.
[end quote]

Looking back to Raymond's example here:
http://mail.python.org/pipermail/pyt...er/056510.html

[quote]
I propose that in Py3.0, the "and" and "or" operators be simplified to
always return a Boolean value instead of returning the last evaluated
argument.

1) The construct can be error-prone. When an error occurs it can be
invisible to the person who wrote it. I got bitten in published code
that had survived testing and code review:

def real(self):
'Return a vector with the real part of each input element'
# do not convert integer inputs to floats
return self.map(lambda z: type(z)==types.ComplexType and z.real or z)

The code fails silently when z is (0+4i). It took a good while to trace
down a user reported error (when Matlab results disagreed with my matrix
module results) and determine that the real() method contained an error.
Even when traced down, I found it hard to see the error in the code.
Now that I know what to look for, it has not happened again, but I do
always have to stare hard at any "and/or" group to mentally verify each
case.
[end quote]
Dare I suggest that if Raymond wasn't struggling to force the body of his
function real() to be a one-liner, he wouldn't have tried to use the "x
and y or z" syntax that bit him? Brevity is not always a virtue.
--
Steven.

Nov 22 '05 #30
On Fri, 18 Nov 2005 21:05:50 -0800, bo****@gmail.com wrote:

Steven D'Aprano wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?

if cond:
x = true_value
else:
x = false_value

It is easy to read, easy to understand, only one of true_value and
false_value is evaluated. It isn't a one-liner. Big deal. Anyone would
think that newlines cost money or that ever time you used one God killed a
kitten.

How do you put this block into list comprehension or generator
expression ? Why the obsession of these block style ?


Why do you assume that everything you need for your list comprehension has
to go into a single line? Chances are your list comp already calls
functions, so just create one more for it to use.
py> def describe(cond):
.... if cond:
.... return "odd"
.... else:
.... return "even"
....
py> L = [describe(n % 2) for n in range(8)]
py> L
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

One major advantage is that this makes it easier to test your function
describe() in isolation, always a good thing.

Another advantage is that the idiom "call a function" is extensible to
more complex problems:

def describe(n):
if n < 0:
return "negative " + describe(-n)
elif n == 0:
return "zero"
elif n % 2:
return "odd"
else:
return "even"

L = [describe(n) for n in range(8)]

if much easier to understand and follow than using ternary expressions:

# obviously untested
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]

Yes, I've seen ternary expressions nested three and even four deep.

I find it fascinating to read Guido's reasoning for introducing a ternary
statement. From the PEP here http://www.python.org/peps/pep-0308.html he
links to this comment of his:

[quote]
I think Raymond's example is more properly considered an argument for
adding a conditional expression than for removing the current behavior of
the and/or shortcut operators; had we had a conditional expression, he
wouldn't have tried to use the "x and y or z" syntax that bit him.
[end quote]

Looking back to Raymond's example here:
http://mail.python.org/pipermail/pyt...er/056510.html

[quote]
I propose that in Py3.0, the "and" and "or" operators be simplified to
always return a Boolean value instead of returning the last evaluated
argument.

1) The construct can be error-prone. When an error occurs it can be
invisible to the person who wrote it. I got bitten in published code
that had survived testing and code review:

def real(self):
'Return a vector with the real part of each input element'
# do not convert integer inputs to floats
return self.map(lambda z: type(z)==types.ComplexType and z.real or z)

The code fails silently when z is (0+4i). It took a good while to trace
down a user reported error (when Matlab results disagreed with my matrix
module results) and determine that the real() method contained an error.
Even when traced down, I found it hard to see the error in the code.
Now that I know what to look for, it has not happened again, but I do
always have to stare hard at any "and/or" group to mentally verify each
case.
[end quote]
Dare I suggest that if Raymond wasn't struggling to force the body of his
function real() to be a one-liner, he wouldn't have tried to use the "x
and y or z" syntax that bit him? Brevity is not always a virtue.
--
Steven.

Nov 22 '05 #31

Steven D'Aprano wrote:
Why do you assume that everything you need for your list comprehension has
to go into a single line? Chances are your list comp already calls
functions, so just create one more for it to use.
py> def describe(cond):
... if cond:
... return "odd"
... else:
... return "even"
...
py> L = [describe(n % 2) for n in range(8)]
py> L
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
this makes me "jump" from the list comprehension to the function,
harder to follow than 'in place', especially when the function is
simple, it is not necessary. What is the reason for introducing list
comprehension and then later, generator expression when :

a=[]
for x in range(8):
a.append(describe(x%2))
return a

and

for x in range(8):
yield describe(x%2)

can do the same thing ?

Doesn't it violate the general idiom that it better has one and only
one way to do certain thing ? I believe part of the reason is that one
doesn't need to "jump" up and down.

One major advantage is that this makes it easier to test your function
describe() in isolation, always a good thing.

Another advantage is that the idiom "call a function" is extensible to
more complex problems:

def describe(n):
if n < 0:
return "negative " + describe(-n)
elif n == 0:
return "zero"
elif n % 2:
return "odd"
else:
return "even"

L = [describe(n) for n in range(8)]

if much easier to understand and follow than using ternary expressions:

# obviously untested
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]

Yes, I've seen ternary expressions nested three and even four deep.

Now that is obsession for(and bad use of) one-liner. But picking a bad
example of one liner to rule out its effectiveness and readability is a
stretch I would say.

Nov 22 '05 #32

Steven D'Aprano wrote:
Why do you assume that everything you need for your list comprehension has
to go into a single line? Chances are your list comp already calls
functions, so just create one more for it to use.
py> def describe(cond):
... if cond:
... return "odd"
... else:
... return "even"
...
py> L = [describe(n % 2) for n in range(8)]
py> L
['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
this makes me "jump" from the list comprehension to the function,
harder to follow than 'in place', especially when the function is
simple, it is not necessary. What is the reason for introducing list
comprehension and then later, generator expression when :

a=[]
for x in range(8):
a.append(describe(x%2))
return a

and

for x in range(8):
yield describe(x%2)

can do the same thing ?

Doesn't it violate the general idiom that it better has one and only
one way to do certain thing ? I believe part of the reason is that one
doesn't need to "jump" up and down.

One major advantage is that this makes it easier to test your function
describe() in isolation, always a good thing.

Another advantage is that the idiom "call a function" is extensible to
more complex problems:

def describe(n):
if n < 0:
return "negative " + describe(-n)
elif n == 0:
return "zero"
elif n % 2:
return "odd"
else:
return "even"

L = [describe(n) for n in range(8)]

if much easier to understand and follow than using ternary expressions:

# obviously untested
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]

Yes, I've seen ternary expressions nested three and even four deep.

Now that is obsession for(and bad use of) one-liner. But picking a bad
example of one liner to rule out its effectiveness and readability is a
stretch I would say.

Nov 22 '05 #33

Steven D'Aprano wrote:
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]

BTW, the continuation is not necessary I believe.

[ x==0 and "zero" or ["","-"][x < 0] + ("even", "odd")[x%2] for x in
range(8) ]

isn't too bad. though I like the C one a bit more(as it doesn't
overload the and/or)

[ x==0 ? "zero" : ["","-"][x < 0] + ("even", "odd")[x%2] for x in
range(8) ]

As it is still a very straight forward flow(from left to right, without
"internal decision split in between").

Nov 22 '05 #34

Steven D'Aprano wrote:
L = ["zero" if n == 0 else \
"negative " + ("odd" if n % 2 else "even") if n < 0 else \
"odd" if n % 2 else "even" for n in range(8)]

BTW, the continuation is not necessary I believe.

[ x==0 and "zero" or ["","-"][x < 0] + ("even", "odd")[x%2] for x in
range(8) ]

isn't too bad. though I like the C one a bit more(as it doesn't
overload the and/or)

[ x==0 ? "zero" : ["","-"][x < 0] + ("even", "odd")[x%2] for x in
range(8) ]

As it is still a very straight forward flow(from left to right, without
"internal decision split in between").

Nov 22 '05 #35
> WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?
if cond:
x = true_value
else:
x = false_value


Let me tell you something: I'm not a one-liner coder, but sometimes It
is necesary.
For example:
I need to translate data from a DataField to Another.

def Evaluate(condition,truepart,falsepart):
if condition:
return truepart
else:
return falsepart

dOldDataFields = {}
dNewDataFields = {}

dNewDataFields = {
'CODE': dOldDataFields['CODEDATA'],
'DATE': dOldDataFields['DATE'],
'CONTACT': Evaluate(dOldDataFields['CONTACTTYPE']==2,
dOldDataFields['FIRSTCONTACT'], dOldDataFields['SECONDCONTACT'])
}

With this, I created a new dic very easy, saving in
dNewDataFields['CONTACT'] the value of dOldDataFields['FIRSTCONTACT']
or the value of dOldDataFields['SECONDCONTACT'] depending on
dOldDataFields['CONTACTTYPE']. How you do this in a practic way without
the use of one-line code? It is needed! You can't avoid it! Even using
a = [if_false_expr, if_true_expr][predicate] or a function, you'll
always have to use a one-line code (for this purpose, of course).

Daniel

Nov 23 '05 #36

This could be done easier this way:

L = [('odd','even')[n%2] for i in range(8)]

Nov 23 '05 #37

This could be done easier this way:

L = [('even','odd')[n%2] for n in range(8)]

Nov 23 '05 #38

Luis M. Gonzalez wrote:
This could be done easier this way:

L = [('even','odd')[n%2] for n in range(8)]


That is even/odd, his(created to demonstrate the uglies of ternary) has
4 states, zero, -/+ then even/odd.

Nov 23 '05 #39
Daniel Crespo wrote:
Let me tell you something: I'm not a one-liner coder, but sometimes It
is necesary.
For example:
I need to translate data from a DataField to Another.

def Evaluate(condition,truepart,falsepart):
if condition:
return truepart
else:
return falsepart

dOldDataFields = {}
dNewDataFields = {}

dNewDataFields = {
'CODE': dOldDataFields['CODEDATA'],
'DATE': dOldDataFields['DATE'],
'CONTACT': Evaluate(dOldDataFields['CONTACTTYPE']==2,
dOldDataFields['FIRSTCONTACT'], dOldDataFields['SECONDCONTACT'])
}

With this, I created a new dic very easy, saving in
dNewDataFields['CONTACT'] the value of dOldDataFields['FIRSTCONTACT']
or the value of dOldDataFields['SECONDCONTACT'] depending on
dOldDataFields['CONTACTTYPE']. How you do this in a practic way without
the use of one-line code? It is needed! You can't avoid it!


if you use less verbose names, you can do the same thing in less than half
the number of characters, without a single oneliner:

def convert(old):

new = dict(
CODE=old['CODEDATA'],
DATE=old['DATE']
)

if old['CONTACTTYPE'] == 2:
new['CONTACT'] = old['FIRSTCONTACT']
else:
new['CONTACT'] = old['SECONDCONTACT']

return new

</F>

Nov 23 '05 #40

Fredrik Lundh wrote:
Daniel Crespo wrote:
Let me tell you something: I'm not a one-liner coder, but sometimes It
is necesary.
For example:
I need to translate data from a DataField to Another.

def Evaluate(condition,truepart,falsepart):
if condition:
return truepart
else:
return falsepart

dOldDataFields = {}
dNewDataFields = {}

dNewDataFields = {
'CODE': dOldDataFields['CODEDATA'],
'DATE': dOldDataFields['DATE'],
'CONTACT': Evaluate(dOldDataFields['CONTACTTYPE']==2,
dOldDataFields['FIRSTCONTACT'], dOldDataFields['SECONDCONTACT'])
}

With this, I created a new dic very easy, saving in
dNewDataFields['CONTACT'] the value of dOldDataFields['FIRSTCONTACT']
or the value of dOldDataFields['SECONDCONTACT'] depending on
dOldDataFields['CONTACTTYPE']. How you do this in a practic way without
the use of one-line code? It is needed! You can't avoid it!


if you use less verbose names, you can do the same thing in less than half
the number of characters, without a single oneliner:

def convert(old):

new = dict(
CODE=old['CODEDATA'],
DATE=old['DATE']
)

if old['CONTACTTYPE'] == 2:
new['CONTACT'] = old['FIRSTCONTACT']
else:
new['CONTACT'] = old['SECONDCONTACT']

return new


I don't find your code any more readable than the OP's
equivalent code:

def convert(old):
new = {
CODE: old['CODEDATA'],
DATE: old['DATE'],
CONTACT: old['FIRSTCONTACT'] \
if old['CONTACTTYPE'] == 2 \
else old['OLDDCONTACT']
}
return new

The OPs code make one pass through the dict, your's makes
two. I do not know what effect (if any) that has in the case of
a very large dict.

Nov 23 '05 #41
On Wed, 23 Nov 2005 07:01:58 -0800, Daniel Crespo wrote:
WHY WHY WHY the obsession with one-liners? What is wrong with the good old
fashioned way?
if cond:
x = true_value
else:
x = false_value


Let me tell you something: I'm not a one-liner coder, but sometimes It
is necesary.


I'm not arguing for multi-line code just for the sake of using more than
one line. I'm against artificially trying to compress a algorithm that is
naturally expressed in two or more lines into one line.

For example:
I need to translate data from a DataField to Another.

def Evaluate(condition,truepart,falsepart):
if condition:
return truepart
else:
return falsepart

dOldDataFields = {}
dNewDataFields = {}
Why do you bother to initialise dNewDataFields to an empty dict when you
then populate it in the very next statement?

dNewDataFields = {
'CODE': dOldDataFields['CODEDATA'],
'DATE': dOldDataFields['DATE'],
'CONTACT': Evaluate(dOldDataFields['CONTACTTYPE']==2,
dOldDataFields['FIRSTCONTACT'], dOldDataFields['SECONDCONTACT'])
}
Doesn't look like a one-liner to me. You've called Evaluate, which takes
five lines by my count.

With this, I created a new dic very easy, saving in
dNewDataFields['CONTACT'] the value of dOldDataFields['FIRSTCONTACT']
or the value of dOldDataFields['SECONDCONTACT'] depending on
dOldDataFields['CONTACTTYPE']. How you do this in a practic way without
the use of one-line code? It is needed! You can't avoid it! Even using
a = [if_false_expr, if_true_expr][predicate] or a function, you'll
always have to use a one-line code (for this purpose, of course).


Again, I am not arguing for needlessly inflating lines of code, I think
your solution is fine. But just to prove it can be done:

dNewDataFields['CODE'] = dOldDataFields['CODEDATA']
dNewDataFields['DATE'] = dOldDataFields['DATE']
if dOldDataFields['CONTACTTYPE'] == 2:
dNewDataFields['CONTACT'] = dOldDataFields['FIRSTCONTACT']
else:
dNewDataFields['CONTACT'] = dOldDataFields['SECONDCONTACT']
There. The world didn't end.

*wink*

--
Steven.

Nov 23 '05 #42
Steven D'Aprano <st***@REMOVETHIScyber.com.au> writes:
dNewDataFields['CODE'] = dOldDataFields['CODEDATA']
dNewDataFields['DATE'] = dOldDataFields['DATE']
if dOldDataFields['CONTACTTYPE'] == 2:
dNewDataFields['CONTACT'] = dOldDataFields['FIRSTCONTACT']
else:
dNewDataFields['CONTACT'] = dOldDataFields['SECONDCONTACT']

There. The world didn't end.


It gets messy for a more complicated structure:

d = {'x': x1() if x_is_old else x2(),
'y': y1() if y_is_old else y2(),
'z': z1() if z_is_old else z2() }

etc.
Nov 23 '05 #43
Paul Rubin wrote:
It gets messy for a more complicated structure:

d = {'x': x1() if x_is_old else x2(),
'y': y1() if y_is_old else y2(),
'z': z1() if z_is_old else z2() }
etc.


somewhere between the '}' and the '.', a data-driven approach will
be more readable, easier to maintain, and nearly as efficient.

(and with an example as regular as yours, the data table can be auto-
generated...)

</F>

Nov 23 '05 #44
ru***@yahoo.com wrote:
I don't find your code any more readable than the OP's
equivalent code:
the OP's question was

How you do this in a practic way without
the use of one-line code ?
The OPs code make one pass through the dict, your's makes
two. I do not know what effect (if any) that has in the case of
a very large dict.


the OPs code contains five reads and three writes, my and
steven's versions contain four reads and three writes. the
yet-to-be-released ternary operator would remove one read
from the OPs code, which makes both alternatives equivalent.

dictionary accesses don't involve passes over the dictionary.

there's a comment on readability and code understanding waiting
to be made here, but I'll leave that for another day.

</F>

Nov 24 '05 #45
ru***@yahoo.com wrote:
Fredrik Lundh wrote:
def convert(old):

new = dict(
CODE=old['CODEDATA'],
DATE=old['DATE']
)

if old['CONTACTTYPE'] == 2:
new['CONTACT'] = old['FIRSTCONTACT']
else:
new['CONTACT'] = old['SECONDCONTACT']

return new

I don't find your code any more readable than the OP's
equivalent code:

def convert(old):
new = {
CODE: old['CODEDATA'],
DATE: old['DATE'],
CONTACT: old['FIRSTCONTACT'] \
if old['CONTACTTYPE'] == 2 \
else old['OLDDCONTACT']
}
return new

The problem I have with your code is that it is too
similar to:

def convert(old):
new = {
CODE: old['CODEDATA'],
DATE: old['DATE'],
CONTACT: old['FIRSTCONTACT'] }
if old['CONTACTTYPE'] == 2:
else: old['OLDDCONTACT']
return new

Yes, the above code is broken. But it *looks* right, at
first glance, unless you train yourself to never write

if cond: TRUE_CLAUSE
else: FALSE_CLAUSE

as a two-liner.

Regardless of whatever benefits the ternary operator is
going to have, in my opinion allowing people to write
TRUE_CLAUSE if COND else FALSE_CLAUSE will increase the
amount of poorly written, hard to read code.

The OPs code make one pass through the dict, your's makes
two.
The original code binds a name to an empty dict, then
rebinds the name to a populated dict.

Your code simply creates the dict in one step.

Fredrik's code creates an initial dict, then adds a new
key and value to it. That's hardly making two passes
through the dict -- what does that even mean?

I do not know what effect (if any) that has in the case of
a very large dict.

Quick and dirty speed test:

py> from time import time
py> def makedict1():
.... return dict.fromkeys(range(1000))
....
py> def makedict2():
.... D = {}
.... for i in range(1000):
.... D[i]=None
.... return D
....
py> assert makedict1() == makedict2()
py> def test(func, n=100):
.... t = time()
.... for i in range(n):
.... tmp = func()
.... return (time() - t)/n
....
py> test(makedict1)
0.00020779848098754884
py> test(makedict2)
0.00042409896850585936

That's not timing quite the same thing you refer to,
but it is suggestive: if you create an empty dict, and
then populate it one item at a time, it will take
approximately twice as long as creating the non-empty
dict directly.

As a very unscientific, system-dependent, statistically
shoddy ball-park estimate, it looks like each item
assignment to a pre-existing dict takes less than
0.0000002s. So if you had a dict and added another
million items to it, one at a time, it might take an
extra 0.2s in total more than what it would have taken
you if you wrote those one million items in your source
code.

I can live with that.

--
Steven.

Nov 24 '05 #46

Steven D'Aprano wrote:
ru***@yahoo.com wrote:
Fredrik Lundh wrote:
def convert(old):

new = dict(
CODE=old['CODEDATA'],
DATE=old['DATE']
)

if old['CONTACTTYPE'] == 2:
new['CONTACT'] = old['FIRSTCONTACT']
else:
new['CONTACT'] = old['SECONDCONTACT']

return new

I don't find your code any more readable than the OP's
equivalent code:

def convert(old):
new = {
CODE: old['CODEDATA'],
DATE: old['DATE'],
CONTACT: old['FIRSTCONTACT'] \
if old['CONTACTTYPE'] == 2 \
else old['OLDDCONTACT']
}
return new

The problem I have with your code is that it is too
similar to:

def convert(old):
new = {
CODE: old['CODEDATA'],
DATE: old['DATE'],
CONTACT: old['FIRSTCONTACT'] }
if old['CONTACTTYPE'] == 2:
else: old['OLDDCONTACT']
return new


Huh? How is this similar? Even a glance shows the
indentation is different. It has the same results?
Ok. But why would someone want to assign wrong
values to some of the entries, then go back and fix them?
I think either Fredrick's code or the code I posted is
clearer than this.
Yes, the above code is broken. But it *looks* right, at
first glance,
Yes, I see the error. OLDDCONTACT should be
OLDCONTACT. Are you going to suggest Enum's? :-)
unless you train yourself to never write

if cond: TRUE_CLAUSE
else: FALSE_CLAUSE

as a two-liner.
Oh, that error too... But that error is a compile time
syntax error. Your argument would be much stronger
if it was not a syntax error, but resulted in erroneous
program behavior.
Regardless of whatever benefits the ternary operator is
going to have, in my opinion allowing people to write
TRUE_CLAUSE if COND else FALSE_CLAUSE will increase the
amount of poorly written, hard to read code.


1. Your definitions of hard to read are not the same as mine.
2. Good documentation can mitigate this somewhat.
3. The benefits of being able to write easier to read code
by people with good judgement outweighs the downside.

Nov 24 '05 #47

Fredrik Lundh wrote:
ru***@yahoo.com wrote:
I don't find your code any more readable than the OP's
equivalent code:
the OP's question was

How you do this in a practic way without
the use of one-line code ?


I know. But you compared the readability of code with
one-liners and long variable names with the readability
of code with no one-liners and short variable names.
I thought that most of the readability improvement was
due to the long-to-short name change. So I posted what
I hoped was code equivalent to what you quoted, but
using your short names and a one-liner "then-if-else"
(on 3 lines :-) It satisfied me that the readability
improvement was due to the short varible names.
The OPs code make one pass through the dict, your's makes
two. I do not know what effect (if any) that has in the case of
a very large dict.


the OPs code contains five reads and three writes, my and
steven's versions contain four reads and three writes. the
yet-to-be-released ternary operator would remove one read
from the OPs code, which makes both alternatives equivalent.

dictionary accesses don't involve passes over the dictionary.


I was actually thinking of the effects of hardware
memory cache...
there's a comment on readability and code understanding waiting
to be made here, but I'll leave that for another day.


Nov 24 '05 #48
ru***@yahoo.com wrote
dictionary accesses don't involve passes over the dictionary.


I was actually thinking of the effects of hardware
memory cache...


yeah, sure.

</F>

Nov 24 '05 #49

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

6 posts views Thread by praba kar | last post: by
reply views Thread by Daniel Crespo | last post: by
15 posts views Thread by Arthur Dent | last post: by
7 posts views Thread by kretik | last post: by
4 posts views Thread by raiderdav | last post: by
1 post views Thread by Waqarahmed | last post: by
reply views Thread by Salome Sato | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.