Re: Rant (was Re: x*x if x10

2008-07-28 Thread greg

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
--
http://mail.python.org/mailman/listinfo/python-list


Rant (was Re: x*x if x10

2008-07-27 Thread DaveM
On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 [EMAIL PROTECTED] wrote:

On Jul 27, 10:13 pm, ssecorp [EMAIL PROTECTED] wrote:
 I have seen somewhere that you can write something like:

 x*x if x10
 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-value if condition else 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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Karen Tracey
On Sun, Jul 27, 2008 at 10:17 AM, DaveM [EMAIL PROTECTED] wrote:

 On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 [EMAIL PROTECTED]
 wrote:

 On Jul 27, 10:13 pm, ssecorp [EMAIL PROTECTED] wrote:
  I have seen somewhere that you can write something like:

  x*x if x10
  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-value if condition else 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?


In fact the PEP for this construct states:

The motivating use case was the prevalance of error-prone attempts
to achieve the same effect using and and or.

See: http://www.python.org/dev/peps/pep-0308/

Karen
--
http://mail.python.org/mailman/listinfo/python-list

Re: Rant (was Re: x*x if x10

2008-07-27 Thread Diez B. Roggisch

DaveM schrieb:

On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 [EMAIL PROTECTED] wrote:


On Jul 27, 10:13 pm, ssecorp [EMAIL PROTECTED] wrote:

I have seen somewhere that you can write something like:



x*x if x10
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-value if condition else 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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Gary Herron

DaveM wrote:

On Sun, 27 Jul 2008 05:24:36 -0700 (PDT), alex23 [EMAIL PROTECTED] wrote:

  

On Jul 27, 10:13 pm, ssecorp [EMAIL PROTECTED] wrote:


I have seen somewhere that you can write something like:
  


  

x*x if x10
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-value if condition else 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
  


--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Marc 'BlackJack' Rintsch
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Diez B. Roggisch

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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread ssecorp
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.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread alex23
On Jul 28, 1:26 am, ssecorp [EMAIL PROTECTED] wrote:
 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!
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread DaveM
On Sun, 27 Jul 2008 16:57:14 +0200, Diez B. Roggisch [EMAIL PROTECTED]
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Gary Herron

DaveM wrote:

On Sun, 27 Jul 2008 16:57:14 +0200, Diez B. Roggisch [EMAIL PROTECTED]
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
  


--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Diez B. Roggisch

DaveM schrieb:

On Sun, 27 Jul 2008 16:57:14 +0200, Diez B. Roggisch [EMAIL PROTECTED]
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread DaveM
On Sun, 27 Jul 2008 16:41:19 +0200, Diez B. Roggisch [EMAIL PROTECTED]
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Diez B. Roggisch


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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Terry Reedy

DaveM wrote:

On Sun, 27 Jul 2008 16:57:14 +0200, Diez B. Roggisch [EMAIL PROTECTED]



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

--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Anders J. Munch

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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread DaveM
On Sun, 27 Jul 2008 09:28:28 -0700, Gary Herron [EMAIL PROTECTED]
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread DaveM
On Sun, 27 Jul 2008 19:46:32 +0200, Diez B. Roggisch [EMAIL PROTECTED]
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Terry Reedy



DaveM wrote:

On Sun, 27 Jul 2008 19:46:32 +0200, Diez B. Roggisch [EMAIL PROTECTED]
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.

--
http://mail.python.org/mailman/listinfo/python-list


Re: Rant (was Re: x*x if x10

2008-07-27 Thread Diez B. Roggisch

Terry Reedy schrieb:



DaveM wrote:
On Sun, 27 Jul 2008 19:46:32 +0200, Diez B. Roggisch 
[EMAIL PROTECTED]

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
--
http://mail.python.org/mailman/listinfo/python-list