else on the same line - howto

H

Helmut Jarausch

Sorry for this trivial question

Since Python lacks conditional expression

like

k+= (dy >= 0 ? 1 : -1)

I would like to write
if dy >= 0 : k+= 1; else: k-= 1

instead of
if dy >= 0 : k+= 1
else : k-= 1

but I don't know the exact syntax for writing
the 'else' clause onto the same line.

Thanks for a hint,

Helmut Jarausch
RWTH-Aachen University
Germany
 
D

Duncan Booth

k+= (dy >= 0 ? 1 : -1)

I would like to write
if dy >= 0 : k+= 1; else: k-= 1

instead of
if dy >= 0 : k+= 1
else : k-= 1

but I don't know the exact syntax for writing
the 'else' clause onto the same line.

Thanks for a hint,

Hint: does using a newline character really cause you that much heartache?

There is no Python syntax for writing the else on the same line. Learn to
live with it. Anyone who has to maintain your code will thank you for
laying it out cleanly instead of cramping everything up onto a single line.

The clearest thing here would be to extract your intention out into a
separate function. For example:

def direction(delta):
if delta >= 0: return 1
return -1

then use it:

k += direction(dy)
 
G

Gerrit Holl

Helmut said:
Sorry for this trivial question

Since Python lacks conditional expression

like

k+= (dy >= 0 ? 1 : -1)

See PEP 308 and google for PEP 308 (on Google groups) for background
information.
I would like to write
if dy >= 0 : k+= 1; else: k-= 1

You can't.
instead of
if dy >= 0 : k+= 1
else : k-= 1

Why do you want to obscure you're own code?

Gerrit Holl.
 
D

Diez B. Roggisch

Since Python lacks conditional expression
like

k+= (dy >= 0 ? 1 : -1)

You can do it - however, it has some implications:

k += [1,-1][dy < 0]

or

k += [-1,1][dy >= 0]

However, keep in mind that this expression is strictly evaluated. That means
that both parts of the list are evaluated _before_ one is selected using
the boolean index op. That can cause trouble:

k += [expensiveOp1(arg1), expensiveOp2(arg2)][dy >= 0]

will always evaluate both expensiveOps

You can overcome that by lazy evaluation using a lambda:

k += [lambda: expensiveOp1(arg1), lambda: expensiveOp2(arg2)][dy >= 0]()

But this is faar from beeing readable, so in the end I have to agree to the
other posters: Don't do it!

Regards,

Diez
 
T

Terry Reedy

Helmut Jarausch said:
Since Python lacks conditional expression
like

k+= (dy >= 0 ? 1 : -1)

For this specific example:

k+= (dy >= 0 and 1 or -1)

But don't do this unless and until you 1) understand why this works
and why the and branch must be non-null and what happens if it is null
(this is discussed both in the FAQ and PEP 308) AND 2) accept
responsibility for always remembering the caution.

Terry J. Reedy
 
P

Peter Hansen

Terry said:
For this specific example:

k+= (dy >= 0 and 1 or -1)

But don't do this unless and until you 1) understand why this works
and why the and branch must be non-null and what happens if it is null
(this is discussed both in the FAQ and PEP 308) AND 2) accept
responsibility for always remembering the caution.

Is it "non-null" or "non-false"?
 
A

Alex Martelli

Peter said:
Is it "non-null" or "non-false"?

Non-false. Anyway, if one really wants to obfuscate, why not:

k += 1 - 2*(dy<0)

??? Now THAT is clever -- none of those plebeian, obvious

if dy>=0: k += 1
else: k -= 1

TWO-liners... first of all, if even your boss can understand
what your code is doing, you're not being clever enough and your
next raise or even your job could be at risk; second, with the
cost of lines these days, obviously saving a WHOLE line _IS_
worth all of the obfuscation in the world.


Alex

PS: I did think about inserting smilies, but I think colons and
closed parentheses are going up in price, too, so, in the same
spirit as the saving-one-line above, I decided I'd better not.
 
C

Caleb Land

Helmut Jarausch said:
Sorry for this trivial question

Since Python lacks conditional expression

like

k+= (dy >= 0 ? 1 : -1)

I would like to write
if dy >= 0 : k+= 1; else: k-= 1

instead of
if dy >= 0 : k+= 1
else : k-= 1

but I don't know the exact syntax for writing
the 'else' clause onto the same line.

If you really want such a thing you could make a generic function that
would replace ?:

def iif(cond, t, f):
if cond:
return t
else:
return f

k += iif(dy >= 0, 1, -1)

-Caleb
 
P

Peter Hansen

Alex said:
[snip]
Alex

PS: I did think about inserting smilies, but I think colons and
closed parentheses are going up in price, too, so, in the same
spirit as the saving-one-line above, I decided I'd better not.

Careful, Alex. I hear there's a world-wide shortage of postscripts,
too, so you should use them sparingly as well.

This message sent without smileys, parentheses, colons, or postscripts,
in the interests of economy.

-Peter
 
A

Alex Martelli

Peter said:
Alex said:
[snip]
Alex

PS: I did think about inserting smilies, but I think colons and
closed parentheses are going up in price, too, so, in the same
spirit as the saving-one-line above, I decided I'd better not.

Careful, Alex. I hear there's a world-wide shortage of postscripts,
too, so you should use them sparingly as well.

Why, of course -- that's the reason postscript printers are so much
costlier than other kinds. However, since I did splurge for a postscript
printer for my home LAN, I think I do get to indulge myself occasionally.


Alex
 
H

Helmut Jarausch

Caleb said:
If you really want such a thing you could make a generic function that
would replace ?:

def iif(cond, t, f):
if cond:
return t
else:
return f

k += iif(dy >= 0, 1, -1)

Thanks to all who have replied. It's amazing how many different
solutions are possible in Python.
Among all such a solution by a function is most readable (to me)
and I can well imagine such a function a builtin.
I have been teaching course in C++ to beginners and made the experience
that well chosen conditional expression are not obscure.
One can misuse any feature of a language to write obscure code.
Especially for the expression of a 'return' statement a conditional
expression might be a good idea.

Helmut.
 
H

Helmut Jarausch

Caleb said:
If you really want such a thing you could make a generic function that
would replace ?:

def iif(cond, t, f):
if cond:
return t
else:
return f

k += iif(dy >= 0, 1, -1)

Thanks to all who have replied. It's amazing how many different
solutions are possible in Python.
Among all such a solution by a function is most readable (to me)
and I can well imagine such a function a builtin.
I have been teaching course in C++ to beginners and made the experience
that well chosen conditional expression are not obscure.
One can misuse any feature of a language to write obscure code.
Especially for the expression of a 'return' statement a conditional
expression might be a good idea.

Helmut.
 
H

Helmut Jarausch

Caleb said:
If you really want such a thing you could make a generic function that
would replace ?:

def iif(cond, t, f):
if cond:
return t
else:
return f

k += iif(dy >= 0, 1, -1)

Thanks to all who have replied. It's amazing how many different
solutions are possible in Python.
Among all such a solution by a function is most readable (to me)
and I can well imagine such a function a builtin.
I have been teaching course in C++ to beginners and made the experience
that well chosen conditional expression are not obscure.
One can misuse any feature of a language to write obscure code.
Especially for the expression of a 'return' statement a conditional
expression might be a good idea.

Helmut.
 
H

Helmut Jarausch

Terry said:
For this specific example:

k+= (dy >= 0 and 1 or -1)

But don't do this unless and until you 1) understand why this works
and why the and branch must be non-null and what happens if it is null
(this is discussed both in the FAQ and PEP 308) AND 2) accept
responsibility for always remembering the caution.
Thanks to all who have replied. It's amazing how many different
solutions are possible in Python.
Among all such a solution by a function is most readable (to me)
and I can well imagine such a function a builtin.
I have been teaching course in C++ to beginners and made the experience
that well chosen conditional expression are not obscure.
One can misuse any feature of a language to write obscure code.
Especially for the expression of a 'return' statement a conditional
expression might be a good idea.
So it's a pity that PEP 308 has been rejected since nobody is forced to
use such a construct if he/she doesn't like to.


Helmut.
 
H

Helmut Jarausch

Terry said:
For this specific example:

k+= (dy >= 0 and 1 or -1)

But don't do this unless and until you 1) understand why this works
and why the and branch must be non-null and what happens if it is null
(this is discussed both in the FAQ and PEP 308) AND 2) accept
responsibility for always remembering the caution.
Thanks to all who have replied. It's amazing how many different
solutions are possible in Python.
Among all such a solution by a function is most readable (to me)
and I can well imagine such a function a builtin.
I have been teaching course in C++ to beginners and made the experience
that well chosen conditional expression are not obscure.
One can misuse any feature of a language to write obscure code.
Especially for the expression of a 'return' statement a conditional
expression might be a good idea.
So it's a pity that PEP 308 has been rejected since nobody is forced to
use such a construct if he/she doesn't like to.

Helmut.
 
A

Alex Martelli

Helmut Jarausch wrote:
...
So it's a pity that PEP 308 has been rejected since nobody is forced to
use such a construct if he/she doesn't like to.

Anybody programming as a part of a group can be "forced to use a construct"
when maintaining others' code that uses it, or pair-programming with another
who does; and similarly for anybody who consults for that group, or teaches
Python to people who need to join such a group, or writes books which are
meant to teach or at least entirely cover the language, and so on.

Only in a hypothetical world where each programmer "owns" his or her code
*exclusively* and never shows those sources to anybody else would your
contention about "nobody is forced" hold water. In a world where groups of
people cooperate, courses are taught, books are written, and so on, it
doesn't. Each feature added to a language carries weight for _everybody_
who uses that language, except for the hypothetical isolated programmer (so
isolated he never even downloads code from the net to adapt it for his or
her purposes -- QUITE hypothetical nowadays).


Alex
 
A

Asun Friere

Alex Martelli said:
Helmut Jarausch wrote:
...

Anybody programming as a part of a group can be "forced to use a construct"
when maintaining others' code that uses it, ...

That I would have thought, was one of the best arguments _for_ 308.
Ie, since people want this construct they will write it in all kinds
of ways, (some unsafe). Against this 308 was proposing that one
obvious way to do it be adopted -- with obvious benefits for
maintaining other people's code. Of course the adoption of a single
idiom would accomplish this as well.

Correct me if I'm wrong, but the way I understand it the reason 308
did not gain favour wasn't on the basis of "I don't wanna use it so
nobody should have it" (which is an non argument), nor of "When I'm
maintaining someone else's code I don't want to be confronted with a
single easily recognised construct" (which is an anti-argument).
Rather, it was felt that the necessity for this construct was not
sufficient to justify the 'feature-creep' involved. Given the
imperative to keep the language simple, and against the many requests
for new features, the 'ternary operator' just didn't cut it.
 
A

Alex Martelli

Asun said:
That I would have thought, was one of the best arguments _for_ 308.
Ie, since people want this construct they will write it in all kinds
of ways, (some unsafe).

....and if and when that happens, you can always remold any obscure
and/or unsafe construct to use, instead, the "one obvious way to
do it" -- if/else WITHOUT any compulsion at all to keep them both
on the same line. Changing code that's obviously bad to code
that's obviously good is one of the most typical actions during
maintenance. For example, you notice a snippet:

if(x > y): return(True)
else: return(False)

sigh (if that), and turn it into the one obviously right form:

return x>y

removing the redundant parentheses (violating PEP 8) as well
as collapsing the redundantly baroque structure. As long as
the language does provide one obvious way to do it, it's a minor
issue that other not-so-obvious ways are almost inevitably
going to be there, too; in practice, you get no objections about
moving from non-obvious to obvious (except from deliberately
bloody-minded people who are only out to annoy, but don't judge
the proportion of such people from traffic on Usenet: they're
much rarer in real life:).

But if the language "goes out of its way" to take the trouble
to add a specific construct for a task, you're _guaranteed_
that some people in the group will want to use that construct
and in fact will bitterly object to any attempt to remold it
away or negotiate its non-use in coding conventions. And of
course such construct-lovers have a point: if the language
has adopted the construct, you cannot any more argue that the
construct should always be avoided -- if it's in the language,
there MUST be occasions in which the construct is the best
way to express something (assuming you do accept the language
rather than design a subset of it in coding conventions).

Therefore, it is disingenuous to claim, as Helmut does:

"nobody is forced to use such a construct if he/she doesn't like to."

this is FALSE: everybody who programs in a group is LIKELY to be
forced to use (read, maintain, ...) such a construct whether they
like it or not.
Against this 308 was proposing that one
obvious way to do it be adopted -- with obvious benefits for
maintaining other people's code. Of course the adoption of a single
idiom would accomplish this as well.

The obvious single idiom is the if/else statement, and objections
to it come mostly from people who idolize "one-liners" -- see the
subject of this thread again. Passing PEP 308 would not outlaw
the if/else statement, of course.

We've been through it in the recent past with such innocuous language
additions as += -- suddenly, the obvious-to-anybody code:

widgets = widgets + 1

was NOT any more "the one obvious way to do it", and the equivalent

widgets += 1

creeped all over our code. So be it -- maybe that addition was
worthwhile, and it's far too late to undo it, anyway. But far from
giving "obvious benefits for maintaining other people's code", such
additions of features give PROBLEMS in this regard.

Correct me if I'm wrong, but the way I understand it the reason 308
did not gain favour wasn't on the basis of "I don't wanna use it so
nobody should have it" (which is an non argument), nor of "When I'm
maintaining someone else's code I don't want to be confronted with a
single easily recognised construct" (which is an anti-argument).

Re-read the HUGE threads of the time and try to divine everybody's
reasons for voting the way they did: I'm not any better placed for
reading into others' mind than you are. But claiming as a
"non argument" the line of reasoning "I don't want to use it, the
ONLY way I'll be able to not use it [in a situation where groups
of people cooperate] is if it's not in the language, so it should
not be in the language" is absurd. It's a perfectly good argument.

As for recognizing, in other people's code, the goofy and obscure
constructions they will often employ, that's a matter of skill and
experience in software reading and maintenance -- after a while you
get to make good guesses about what programming languages certain
people had previously been exposed to, just from exactly what
malapropisms they're most prone to. *BUT* if their obscure and
goofy anti-idioms can be shown to be in definite violation of the
language's style and idioms, *YOU GET TO TAKE THEM OUT* and change
them into the simple, readable forms you prefer. If the language
blesses their usage, YOU'RE STUCK WITH IT in most situations of
practical importance.
Rather, it was felt that the necessity for this construct was not
sufficient to justify the 'feature-creep' involved. Given the
imperative to keep the language simple, and against the many requests
for new features, the 'ternary operator' just didn't cut it.

This is no doubt a factor: each new feature needs to fully carry
its weight and then some. But against this you often hear people
defending a new proposed feature in terms of "and if you don't
like it you don't have to use it", just as is being attempted here:
it's important to understand that this defense is totally fallacious,
and why. Of course it gets worse exponentially fast with the number
of "don't have to use it" features: if there are ten such features,
then you don't have one language any more, you have a bit more than
a thousand dialects (2 to the 10th power) defined by the subsets of
the too-big language that one IS allowed/encouraged to use in any
given group of programmers. Avoiding such fragmentation of the
language community is part of why there IS social pressure to use -- in
appropriate ways -- those features that ARE in the language: to keep
us all using the same language rather than 1024 partially overlapping
subsets thereof. But the root of the problem is with each single
feature that gets added -- and the "don't have to use it" fallacious
and mendacious argument can often lull some people into accepting that
"each single feature", which is why it IS so important to show it
up as BEING mendacious, fallacious, misleading, just plain WRONG.

I could have lived with python-plus-ternary, though I'm a bit happier
with plain good old Python. But I have less tolerance for this
erroneous and destructive line of reasoning!-)


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,269
Messages
2,571,338
Members
48,028
Latest member
chasetony

Latest Threads

Top