By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
464,332 Members | 1,103 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 464,332 IT Pros & Developers. It's quick & easy.

Rant (was Re: x*x if x>10

P: n/a
On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 <wu*****@gmail.comwrote:
>On Jul 27, 10:13*pm, ssecorp <circularf...@gmail.comwrote:
>I have seen somewhere that you can write something like:
>x*x if x>10
but exactly that doesn't work and I can't get any variation to work.
>It's called a ternary operator. The format is:
<label= <true-valueif <conditionelse <false-value>
I've seen the PERL saying/motto/boast, "There's more than one way to do it"
derided on more than one occasion on this group so what's the reason for
this additional way to put an if else statement on one line? Are "and" and
"or" constructions to produce the same effect not supported for this use?

And while I'm on my high horse, I'd like to bring up list concatenations. I
recently needed to concatenate 5 lists, which doesn't sound a particularly
rare requirement to me. My first attempt was a straightforward loop
extending an empty list. That worked fine but looked like an awful bulky
solution. Afterwards I tried various formulae using "reduce" , falling foul
of the "=" catch on one occasion. Now I'm not a professional programmer, so
there may be good reasons for a single object to have multiple names in a
program, but it sounds like a recipe for disaster to me. Getting back to the
list concatenation, I finally found the itertools.chain command which is the
most compact and fastest (or second fastest by a trivial amount, I can't
remember which). Along the way, I must have tried/used half a dozen methods,
....which brings me back my initial PERL comment. There's more than one way
to do it in Python, too.

DaveM
Jul 27 '08 #1
Share this Question
Share on Google+
18 Replies

P: n/a
DaveM schrieb:
On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 <wu*****@gmail.comwrote:
>On Jul 27, 10:13 pm, ssecorp <circularf...@gmail.comwrote:
>>I have seen somewhere that you can write something like:
>>x*x if x>10
but exactly that doesn't work and I can't get any variation to work.
>It's called a ternary operator. The format is:
<label= <true-valueif <conditionelse <false-value>

I've seen the PERL saying/motto/boast, "There's more than one way to do it"
derided on more than one occasion on this group so what's the reason for
this additional way to put an if else statement on one line? Are "and" and
"or" constructions to produce the same effect not supported for this use?
You obviously aren't aware of the pitfalls regarding the mis-use of or
and and for this usage.

Try this:
>>a = True
b = 1
c = 2
a and b or c
1
>>a = False
a and b or c
2
>>a = True
b = None
a and b or c
2
>>>

Afterwards I tried various formulae using "reduce" , falling foul
of the "=" catch on one occasion. Now I'm not a professional programmer, so
there may be good reasons for a single object to have multiple names in a
program, but it sounds like a recipe for disaster to me.

Can you tell us what you mean by "several names of one object"? You mean
this?

a = range(10)
b = a

id(a) == id(b)
? Passing references instead of values is an extremely important concept
of many languages, without it you would end up copying most of the time.

Getting back to the
list concatenation, I finally found the itertools.chain command which is the
most compact and fastest (or second fastest by a trivial amount, I can't
remember which). Along the way, I must have tried/used half a dozen methods,
...which brings me back my initial PERL comment. There's more than one way
to do it in Python, too.
Any non-trivial task has that property. I don't know enough perl to have
an example ready that shows something that python has only one way of
doing and perl has several.

But I *do* know that taking the python zen literally is fruitless.
Diez
Jul 27 '08 #2

P: n/a
On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
DaveM schrieb:
>Getting back to the
list concatenation, I finally found the itertools.chain command which
is the most compact and fastest (or second fastest by a trivial amount,
I can't remember which). Along the way, I must have tried/used half a
dozen methods, ...which brings me back my initial PERL comment. There's
more than one way to do it in Python, too.

Any non-trivial task has that property. I don't know enough perl to have
an example ready that shows something that python has only one way of
doing and perl has several.

But I *do* know that taking the python zen literally is fruitless.
I think it should be taken more literally than the wrong reduction to
"there should be only one way". People tend to forget "obvious" and
"preferably" all the time.

Ciao,
Marc 'BlackJack' Rintsch
Jul 27 '08 #3

P: n/a
DaveM wrote:
On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 <wu*****@gmail.comwrote:

>On Jul 27, 10:13 pm, ssecorp <circularf...@gmail.comwrote:
>>I have seen somewhere that you can write something like:

>>x*x if x>10
but exactly that doesn't work and I can't get any variation to work.

>It's called a ternary operator. The format is:
<label= <true-valueif <conditionelse <false-value>

I've seen the PERL saying/motto/boast, "There's more than one way to do it"
derided on more than one occasion on this group so what's the reason for
this additional way to put an if else statement on one line? Are "and" and
"or" constructions to produce the same effect not supported for this use?
The "and" and "or" construct which is equivalent to the ternary operator
is quite convoluted and looks nothing like a conditional computation:
(C and [A] or [b])[0]
This is inefficient, and nearly unreadable, which makes the highly
useful ternary operator worthy of a syntactical construct.
The [A], [b] and [0] parts are absolutely necessary in the general case
where A can have values that Python would consider equivalent to False.
If you know A will never be equivalent to False then you can use just this:
C and A or B

Gary Herron

And while I'm on my high horse, I'd like to bring up list concatenations. I
recently needed to concatenate 5 lists, which doesn't sound a particularly
rare requirement to me. My first attempt was a straightforward loop
extending an empty list. That worked fine but looked like an awful bulky
solution. Afterwards I tried various formulae using "reduce" , falling foul
of the "=" catch on one occasion. Now I'm not a professional programmer, so
there may be good reasons for a single object to have multiple names in a
program, but it sounds like a recipe for disaster to me. Getting back to the
list concatenation, I finally found the itertools.chain command which is the
most compact and fastest (or second fastest by a trivial amount, I can't
remember which). Along the way, I must have tried/used half a dozen methods,
...which brings me back my initial PERL comment. There's more than one way
to do it in Python, too.

DaveM
--
http://mail.python.org/mailman/listinfo/python-list
Jul 27 '08 #4

P: n/a
Marc 'BlackJack' Rintsch schrieb:
On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
>DaveM schrieb:
>>Getting back to the
list concatenation, I finally found the itertools.chain command which
is the most compact and fastest (or second fastest by a trivial amount,
I can't remember which). Along the way, I must have tried/used half a
dozen methods, ...which brings me back my initial PERL comment. There's
more than one way to do it in Python, too.
Any non-trivial task has that property. I don't know enough perl to have
an example ready that shows something that python has only one way of
doing and perl has several.

But I *do* know that taking the python zen literally is fruitless.

I think it should be taken more literally than the wrong reduction to
"there should be only one way". People tend to forget "obvious" and
"preferably" all the time.
Good point. The OP found the obvious way of extending. I wonder what his
reasons were to abandon it.
Diez
Jul 27 '08 #5

P: n/a
I might be misunderstanding OP but:

a+b+c+d+e is simple way of concatenating 5 lists...

as a function that takes any amount of lists and concatenates them:
def concat(*args):
c = []
for elem in args:
c += elem
return c

don't know if extend is faster or slower or the same as + :

def concat(*args):
c = []
for elem in args:
c.extend(elem)
return c

I don't know of a built-in.
Jul 27 '08 #6

P: n/a
On Jul 28, 1:26 am, ssecorp <circularf...@gmail.comwrote:
I might be misunderstanding OP but:

a+b+c+d+e is simple way of concatenating 5 lists...

as a function that takes any amount of lists and concatenates them:
def concat(*args):
c = []
for elem in args:
c += elem
return c

don't know if extend is faster or slower or the same as + :

def concat(*args):
c = []
for elem in args:
c.extend(elem)
return c

I don't know of a built-in.
Just to infuriate the OP even further, here's the list comprehension
version :)
>>def concat(*args):
.... return [elem for arg in args for elem in arg]

Hope this helps!
Jul 27 '08 #7

P: n/a
On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
wrote:
>Marc 'BlackJack' Rintsch schrieb:
>On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
>>DaveM schrieb:
Getting back to the list concatenation, I finally found the itertools.chain
command which is the most compact and fastest (or second fastest by a
trivial amount, I can't remember which). Along the way, I must have
tried/used half a dozen methods, ...which brings me back my initial PERL
comment. There's more than one way to do it in Python, too.
>>But I *do* know that taking the python zen literally is fruitless.
>I think it should be taken more literally than the wrong reduction to
"there should be only one way". People tend to forget "obvious" and
"preferably" all the time.
>Good point. The OP found the obvious way of extending. I wonder what his
reasons were to abandon it.
You'll have guessed, I'm sure, that I'm not a professional programmer. This
was the third rewrite of a program to match candidate groups to examiners on
a three day course I run, necessitated on this occasion by a change in the
structure of the course. I originally learnt python as I wrote, and some of
the early code was ugly and verbose, so once the current rewrite was working
I took the opportunity to tidy the code up and document it (yes, I know, but
as I said, I'm an amateur). The list concatenation was an itch I couldn't
scratch:

temp = []
for value in sessexam.values():
temp.extend(value)
c_exam = [name for name in set(temp)] #See what I mean about verbose?
c_exam.sort()
return c_exam

Six lines just didn't feel like it ought to be the best way to do something
so simple. I liked the attempt below better, but was foolish enough to time
it, so that was the end of that.

return sorted(list(set(reduce(lambda x, y: x+y, sessexam.values()))))

The current version (below) is a compromise, but I still feel there _ought_
to be a simple one word command to join multiple lists.

a = list(set(itertools.chain(*sessexam.values())))
a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
return a

DaveM
Jul 27 '08 #8

P: n/a
DaveM wrote:
On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
wrote:

>Marc 'BlackJack' Rintsch schrieb:
>>On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:
DaveM schrieb:

Getting back to the list concatenation, I finally found the itertools.chain
command which is the most compact and fastest (or second fastest by a
trivial amount, I can't remember which). Along the way, I must have
tried/used half a dozen methods, ...which brings me back my initial PERL
comment. There's more than one way to do it in Python, too.
>

>>>But I *do* know that taking the python zen literally is fruitless.

>>I think it should be taken more literally than the wrong reduction to
"there should be only one way". People tend to forget "obvious" and
"preferably" all the time.

>Good point. The OP found the obvious way of extending. I wonder what his
reasons were to abandon it.

You'll have guessed, I'm sure, that I'm not a professional programmer. This
was the third rewrite of a program to match candidate groups to examiners on
a three day course I run, necessitated on this occasion by a change in the
structure of the course. I originally learnt python as I wrote, and some of
the early code was ugly and verbose, so once the current rewrite was working
I took the opportunity to tidy the code up and document it (yes, I know, but
as I said, I'm an amateur). The list concatenation was an itch I couldn't
scratch:

temp = []
for value in sessexam.values():
temp.extend(value)
c_exam = [name for name in set(temp)] #See what I mean about verbose?
c_exam.sort()
return c_exam

Six lines just didn't feel like it ought to be the best way to do something
so simple. I liked the attempt below better, but was foolish enough to time
it, so that was the end of that.

return sorted(list(set(reduce(lambda x, y: x+y, sessexam.values()))))

The current version (below) is a compromise, but I still feel there _ought_
to be a simple one word command to join multiple lists.

a = list(set(itertools.chain(*sessexam.values())))
a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
return a
Didn't someone already answer that. List addition and sum() both do
what you want.
>>A = [1,2,3]
B = [4,5,6]
C = [7,8,9]
>>A+B+C
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>sum([A,B,C], [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

It doesn't get any easier than that.

Gary Herron
DaveM
--
http://mail.python.org/mailman/listinfo/python-list
Jul 27 '08 #9

P: n/a
DaveM schrieb:
On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
wrote:
>Marc 'BlackJack' Rintsch schrieb:
>>On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch wrote:

DaveM schrieb:
Getting back to the list concatenation, I finally found the itertools.chain
command which is the most compact and fastest (or second fastest by a
trivial amount, I can't remember which). Along the way, I must have
tried/used half a dozen methods, ...which brings me back my initial PERL
comment. There's more than one way to do it in Python, too.
>>>But I *do* know that taking the python zen literally is fruitless.
>>I think it should be taken more literally than the wrong reduction to
"there should be only one way". People tend to forget "obvious" and
"preferably" all the time.
>Good point. The OP found the obvious way of extending. I wonder what his
reasons were to abandon it.

You'll have guessed, I'm sure, that I'm not a professional programmer. This
was the third rewrite of a program to match candidate groups to examiners on
a three day course I run, necessitated on this occasion by a change in the
structure of the course. I originally learnt python as I wrote, and some of
the early code was ugly and verbose, so once the current rewrite was working
I took the opportunity to tidy the code up and document it (yes, I know, but
as I said, I'm an amateur). The list concatenation was an itch I couldn't
scratch:

temp = []
for value in sessexam.values():
temp.extend(value)
c_exam = [name for name in set(temp)] #See what I mean about verbose?
c_exam.sort()
return c_exam

Six lines just didn't feel like it ought to be the best way to do something
so simple. I liked the attempt below better, but was foolish enough to time
it, so that was the end of that.

return sorted(list(set(reduce(lambda x, y: x+y, sessexam.values()))))

The current version (below) is a compromise, but I still feel there _ought_
to be a simple one word command to join multiple lists.

a = list(set(itertools.chain(*sessexam.values())))
a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
return a
You are aware that the above is much more than "concatenate a bunch of
lists?" You want unique values & sorting, which are two additional
requirements. I'd say 3 lines of code for three requirements is ok, so

all = sum(sessexam.values(), [])
unique = set(all)
sorted_result = sorted(unique)

And obviously there are more ways to skin *that* cat, some (as
itertools.chain) being less memory intensive:
a = sorted(set(itertools.chain(*sessexam.values())))

It's debatable if this one-liner is really the way to go, but I fail to
see how you expect there to be a specialized builtin for this kind of task.
Diez
Jul 27 '08 #10

P: n/a
On Sun, 27 Jul 2008 16:41:19 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
wrote:

>You obviously aren't aware of the pitfalls regarding the mis-use of or
and and for this usage.
<snip example>

Well, yes, I am (and the way around the problem), but as its never caught me
out (so far), I hadn't considered it.
>Can you tell us what you mean by "several names of one object"? You mean
this?

a = range(10)
b = a

id(a) == id(b)
? Passing references instead of values is an extremely important concept
of many languages, without it you would end up copying most of the time.
OK. I've obviously been thinking about things the wrong way. In Forth you
pass the memory address around, and presumably that's essentially what's
happening when you pass a reference. The problem is, I get caught frequently
in this situation:

a = [1,2,3]

def foo(x):
do_something_with_x
return x

....

Then when I call foo(a), a gets changed. It just isn't the effect I expect
from changing a local.

DaveM
Jul 27 '08 #11

P: n/a
>
>Can you tell us what you mean by "several names of one object"? You mean
this?

a = range(10)
b = a

id(a) == id(b)
? Passing references instead of values is an extremely important concept
of many languages, without it you would end up copying most of the time.

OK. I've obviously been thinking about things the wrong way. In Forth you
pass the memory address around, and presumably that's essentially what's
happening when you pass a reference.
Pretty much, yes. And I for once can say that I've been caught by
modifying e.g. stack-locals instead of heap-objects in C++ by accident.

The problem is, I get caught frequently
in this situation:

a = [1,2,3]

def foo(x):
do_something_with_x
return x

...

Then when I call foo(a), a gets changed. It just isn't the effect I expect
from changing a local.
It's the way things work - mutables are mutables. If you want them to be
modified, use the module copy.

As a rule of thumb, don't return objects you didn't create inside a
function from scratch.

Which is the exact reasoning for the

list.sort

method btw - returning None is supposed to make you aware of the
in-place modification.


Diez
Jul 27 '08 #12

P: n/a
DaveM wrote:
On Sun, 27 Jul 2008 16:57:14 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
You'll have guessed, I'm sure, that I'm not a professional programmer. This
was the third rewrite of a program to match candidate groups to examiners on
a three day course I run, necessitated on this occasion by a change in the
structure of the course. I originally learnt python as I wrote, and some of
the early code was ugly and verbose, so once the current rewrite was working
I took the opportunity to tidy the code up and document it (yes, I know, but
as I said, I'm an amateur). The list concatenation was an itch I couldn't
scratch:

temp = []
for value in sessexam.values():
temp.extend(value)
c_exam = [name for name in set(temp)] #See what I mean about verbose?
c_exam.sort()
return c_exam

Six lines just didn't feel like it ought to be the best way to do something
so simple. I liked the attempt below better, but was foolish enough to time
it, so that was the end of that.

return sorted(list(set(reduce(lambda x, y: x+y, sessexam.values()))))

The current version (below) is a compromise, but I still feel there _ought_
to be a simple one word command to join multiple lists.
There is, as others have posted, but if you are going to dump the lists
into a set, there is no need to concatenate them together first, and it
is better not to. Just dump them directly into set.
>
a = list(set(itertools.chain(*sessexam.values())))
This is a pretty good way of skipping the intermediate long list. Another:

a = set()
for l in sessexam.values():
a.update(set(l))

If course, if sessexam.values() does not need to be ordered and returns
sets instead, the set call in not needed.
a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
return a
If you want all in one line...
return sorted(set(itertools.chain(*sessexam.values())))

There is no virtue to calling list then .sort, since that is what sorted
basically does.

def sorted(iterable):
tem = list(iterable)
tem.sort()
return tem

tjr
tjr

Jul 27 '08 #13

P: n/a
Gary Herron wrote:
>>A = [1,2,3]
>>B = [4,5,6]
>>C = [7,8,9]
>>A+B+C
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>sum([A,B,C], [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Careful now, this can be very slow. sum uses __add__, not __iadd__, which gives
this approach quadratic worst-case runtime.

- Anders
Jul 27 '08 #14

P: n/a
On Sun, 27 Jul 2008 09:28:28 -0700, Gary Herron <gh*****@islandtraining.com>
wrote:

> a = list(set(itertools.chain(*sessexam.values())))
a.sort() #As I write I'm wondering if I really need it sorted. Hmm...
return a
>Didn't someone already answer that. List addition and sum() both do
what you want.
>A = [1,2,3]
B = [4,5,6]
C = [7,8,9]
>A+B+C
[1, 2, 3, 4, 5, 6, 7, 8, 9]
True, although unsuitable for my circumstance.

>sum([A,B,C], [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Ah. I had no luck with sum, but I hadn't realised it needed the "[]" term. I
must read about it again.
>It doesn't get any easier than that.
Not only that, but it's exactly what I was after - and fastest, too,
although speed isn't really an issue. Thank you.

DaveM
Jul 27 '08 #15

P: n/a
On Sun, 27 Jul 2008 19:46:32 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
wrote:

>As a rule of thumb, don't return objects you didn't create inside a
function from scratch.
I wish I'd had that advice when I started learning python. It would have
saved me no end of grief.

DaveM
Jul 27 '08 #16

P: n/a


DaveM wrote:
On Sun, 27 Jul 2008 19:46:32 +0200, "Diez B. Roggisch" <de***@nospam.web.de>
wrote:
>As a rule of thumb, don't return objects you didn't create inside a
function from scratch.
Unless its job is specifically to get/fetch an object (reference
thereto) from someplace the caller cannot or should not access. But
then it should probably not mutate the object before returning the
reference.
>
I wish I'd had that advice when I started learning python. It would have
saved me no end of grief.
I wish I had seen this 'rule' before too.

Jul 27 '08 #17

P: n/a
Terry Reedy schrieb:
>

DaveM wrote:
>On Sun, 27 Jul 2008 19:46:32 +0200, "Diez B. Roggisch"
<de***@nospam.web.de>
wrote:
>>As a rule of thumb, don't return objects you didn't create inside a
function from scratch.

Unless its job is specifically to get/fetch an object (reference
thereto) from someplace the caller cannot or should not access. But
then it should probably not mutate the object before returning the
reference.
I maybe should paraphrase "don't return objects you passed as arguments
from a function". Of course there are exceptions to this rule - but
these are few, the canonical being chained function calls like this:
class Whatever(object):

def do_something(self, arguments):
....
return self

Diez
Jul 27 '08 #18

P: n/a
Diez B. Roggisch wrote:
I maybe should paraphrase "don't return objects you passed as arguments
from a function".
The important thing is that a function shouldn't modify
any object unless it's the express purpose of the function
to do so.

You could call this the "look but don't touch" rule.

--
Greg
Jul 29 '08 #19

This discussion thread is closed

Replies have been disabled for this discussion.