Re: enumerate improvement proposal

2006-10-31 Thread Raymond Hettinger
James Stroud wrote:
> I think that it would be handy for enumerate to behave as such:
>
> def enumerate(itrbl, start=0, step=1):
>i = start
>for it in itrbl:
>  yield (i, it)
>  i += step

I proposed something like this long ago and Guido has already rejected
it.  Part of the reason is that it doesn't match his mental model of
enumerate being about pairing sequence elements with their indices.
Another reason is that the syntax has more than one obvious
interpretation:

 enumerate('abcdef', 2) -->  (2, 'c'), (3, 'd'), ...
 enumerate('abcdef', 2) -->  (0, 'c'), (1, 'd'), ...
 enumerate('abcdef', 2) -->  (2, 'a'), (2, 'b'), ...

Also, the order of arguments is odd in comparison with the output order
-- this suggests a syntax like enumerate(2, 'abcdef') --> (2, 'a'), (3,
'b') ...

FWIW, it is not hard to roll-your-own with something like:

for pagenum, page in izip(count(1), book): ...

The izip/count combination runs at C speed, matches enumerate() in its
efficiency, and is arguably clearer in expressing its intended
behavior.


Raymond

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


Re: enumerate improvement proposal

2006-10-31 Thread Steven D'Aprano
On Mon, 30 Oct 2006 23:42:16 +, Steve Holden wrote:

> Divorce is obviously the only answer. How could you end up marrying 
> someone who counts from one and not zero? ;-)


"Should array indices start at 0 or 1? My compromise of 0.5 was rejected
without, I thought, proper consideration." (Stan Kelly-Bootle)


-- 
Steven.

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


Re: enumerate improvement proposal

2006-10-30 Thread Paddy

James Stroud wrote:
> Steve Holden wrote:
> > How could you end up marrying
> > someone who counts from one and not zero? ;-)
>
> She's the only other person I've ever met who used vi key binding at the
> command line.
>
Wow. Now I see!

It's only Python. Just add one to indices where appropriate, buy her
chocolates. Don't say a thing when you squelch your seventh off-by-one
error. Look interested in the shoe store. (even for the fifth shoe, of
the third store). - *Your partner does vi*

 Whoa!

- Paddy :-)

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


Re: enumerate improvement proposal

2006-10-30 Thread Ben Finney
Mark Elston <[EMAIL PROTECTED]> writes:

> * James Stroud wrote (on 10/30/2006 4:39 PM):
> > She's the only other person I've ever met who used vi key binding
> > at the command line.
>
> Well, there's your problem.  You need to C-x C-f a new mate. :)

I don't have the commitment for that. What if I were to C-x C-v
a few different ones instead?

-- 
 \"If you continue running Windows, your system may become |
  `\ unstable."  -- Microsoft, Windows 95 BSOD message |
_o__)  |
Ben Finney

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


Re: enumerate improvement proposal

2006-10-30 Thread Mark Elston
* James Stroud wrote (on 10/30/2006 4:39 PM):
> Steve Holden wrote:
>> How could you end up marrying someone who counts from one and not 
>> zero? ;-)
> 
> She's the only other person I've ever met who used vi key binding at the 
> command line.
> 
> James
> 
> 

Well, there's your problem.  You need to C-x C-f a new mate. :)

Mark
(Emacs rules)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: enumerate improvement proposal

2006-10-30 Thread James Stroud
Steve Holden wrote:
> How could you end up marrying 
> someone who counts from one and not zero? ;-)

She's the only other person I've ever met who used vi key binding at the 
command line.

James


-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: enumerate improvement proposal

2006-10-30 Thread Steve Holden
James Stroud wrote:
> Diez B. Roggisch wrote:
> 
>>>Okay, I've googled "leaky abstractions" (as was probably your intended
>>>affect with your silence), read the famous essay, and still
>>>don't know what you mean and how it applies to what I have described.
>>>
>>>Do you plan to justify your statement or emptily accuse people of 
>>>violating
>>>esoteric principles?
>>
>>
>>While I can't claim to know what the effbot thinks (the 
>>skull-socks-wearing-python-coder-mindlink-technology is yet to be 
>>developed), I think it's pretty clear what he is after here:
>>
>>Computers compute offsets into data zero-based. Some languages like 
>>pascal completely abstract that away from the user, but python doesn't.
>>
>>So if your colleague/boss/whatever insists on indices being one-based, 
>>this abstraction you introduced for her pretty fast leaks pretty badly. 
>>Consider this simple example:
>>
>>for offset, item in enumerate(some_list, start=1):
>>if item.is_the_chosen_one():
>>chosen_one_offset = offset
>>
>>the_chosen_one = some_list[chosen_one_offset]
>>
>>And bang, its Judas not Petrus who gets the pearly gates inc. stock 
>>options.
>>
>>Diez
> 
> 
> Thank you for this explanation. Very illuminating. I think understand 
> this idea well and the thought of 1 basing this function makes me cringe 
> as much as the next guy (though I lacked the vocabulary to explain 
> exactly why I cringe).
> 
> But you see, weaning this university faculty level economist (who 
> already has her own way of doing everything...and to whom I happen to be 
> married) from the traditional economics tools of gauss and sas towards 
> the more sane and flexible tools of python, numarray, and rpy has been a 
> multi-stage process. Tweaking the chosen abstractions to not be as leaky 
> (thank you and thank Fredrik for introducing me to this vocabulary) is 
> still one of the things I'm working towards. I want to solidify the 
> conversion before I concentrate on nuance.
> 
> So, before too much criticism, I challenge even the most skilled python 
> programmer to find his or her own faculty economist (or statistician or 
> physicist) and get them to radically change their computational tools. 
> When you've walked a mile in my shoes, leaky abstractions won't seem 
> like such a big deal after all.
> 
Divorce is obviously the only answer. How could you end up marrying 
someone who counts from one and not zero? ;-)

regards
  Steve
-- 
Steve Holden   +44 150 684 7255  +1 800 494 3119
Holden Web LLC/Ltd  http://www.holdenweb.com
Skype: holdenweb   http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

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


Re: enumerate improvement proposal

2006-10-30 Thread James Stroud
Diez B. Roggisch wrote:
>> Okay, I've googled "leaky abstractions" (as was probably your intended
>> affect with your silence), read the famous essay, and still
>> don't know what you mean and how it applies to what I have described.
>>
>> Do you plan to justify your statement or emptily accuse people of 
>> violating
>> esoteric principles?
> 
> 
> While I can't claim to know what the effbot thinks (the 
> skull-socks-wearing-python-coder-mindlink-technology is yet to be 
> developed), I think it's pretty clear what he is after here:
> 
> Computers compute offsets into data zero-based. Some languages like 
> pascal completely abstract that away from the user, but python doesn't.
> 
> So if your colleague/boss/whatever insists on indices being one-based, 
> this abstraction you introduced for her pretty fast leaks pretty badly. 
> Consider this simple example:
> 
> for offset, item in enumerate(some_list, start=1):
> if item.is_the_chosen_one():
> chosen_one_offset = offset
> 
> the_chosen_one = some_list[chosen_one_offset]
> 
> And bang, its Judas not Petrus who gets the pearly gates inc. stock 
> options.
> 
> Diez

Thank you for this explanation. Very illuminating. I think understand 
this idea well and the thought of 1 basing this function makes me cringe 
as much as the next guy (though I lacked the vocabulary to explain 
exactly why I cringe).

But you see, weaning this university faculty level economist (who 
already has her own way of doing everything...and to whom I happen to be 
married) from the traditional economics tools of gauss and sas towards 
the more sane and flexible tools of python, numarray, and rpy has been a 
multi-stage process. Tweaking the chosen abstractions to not be as leaky 
(thank you and thank Fredrik for introducing me to this vocabulary) is 
still one of the things I'm working towards. I want to solidify the 
conversion before I concentrate on nuance.

So, before too much criticism, I challenge even the most skilled python 
programmer to find his or her own faculty economist (or statistician or 
physicist) and get them to radically change their computational tools. 
When you've walked a mile in my shoes, leaky abstractions won't seem 
like such a big deal after all.

James

-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: enumerate improvement proposal

2006-10-30 Thread Diez B. Roggisch
> Okay, I've googled "leaky abstractions" (as was probably your intended
> affect with your silence), read the famous essay, and still
> don't know what you mean and how it applies to what I have described.
> 
> Do you plan to justify your statement or emptily accuse people of violating
> esoteric principles?

While I can't claim to know what the effbot thinks (the 
skull-socks-wearing-python-coder-mindlink-technology is yet to be 
developed), I think it's pretty clear what he is after here:

Computers compute offsets into data zero-based. Some languages like 
pascal completely abstract that away from the user, but python doesn't.

So if your colleague/boss/whatever insists on indices being one-based, 
this abstraction you introduced for her pretty fast leaks pretty badly. 
Consider this simple example:

for offset, item in enumerate(some_list, start=1):
 if item.is_the_chosen_one():
 chosen_one_offset = offset

the_chosen_one = some_list[chosen_one_offset]

And bang, its Judas not Petrus who gets the pearly gates inc. stock options.

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


Re: enumerate improvement proposal

2006-10-30 Thread Anders J. Munch
Ben Finney wrote:
> 
> >>> def obstinate_economist_enumerate(items):
> ... enum_iter = iter((i+1, x) for (i, x) in enumerate(items))
> ... return enum_iter

iter is redundant here.

def natural_enumerate_improvement(items, start=0):
 return ((i+start, x) for (i, x) in enumerate(items))

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


Re: enumerate improvement proposal

2006-10-29 Thread James Stroud
Fredrik Lundh wrote:
> James Stroud wrote:
> 
>> The code is for an economist. She is insistent on starting with the 
>> first bin as 1.
> 
> 
> leaky abstractions in reverse, in other words?  that's not a good design 
> approach.
> 
> 
> 

Okay, I've googled "leaky abstractions" (as was probably your intended
affect with your silence), read the famous essay, and still
don't know what you mean and how it applies to what I have described.

Do you plan to justify your statement or emptily accuse people of violating
esoteric principles?

James

-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: enumerate improvement proposal

2006-10-29 Thread Ben Finney
Ben Finney <[EMAIL PROTECTED]> writes:

> >>> print enumerate("ABCDE")
> 
> >>> print list(enumerate("ABCDE"))
> [(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E')]
>
> >> def obstinate_economist_enumerate(items):
> ... seq = [(i+1, x) for (i, x) in enumerate(items)]
> ... return iter(seq)
> ...
> >>> print obstinate_economist_enumerate("ABCDE")
> 
> >>> print list(obstinate_economist_enumerate("ABCDE"))
> [(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')]

An improvement: using a generator so as not to unnecessarily create an
intermediate list from the initial enumerator:

>>> def obstinate_economist_enumerate(items):
... enum_iter = iter((i+1, x) for (i, x) in enumerate(items))
... return enum_iter
...
>>> print obstinate_economist_enumerate("ABCDE")

>>> print list(obstinate_economist_enumerate("ABCDE"))
[(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')]

-- 
 \  "If sharing a thing in no way diminishes it, it is not rightly |
  `\   owned if it is not shared."  -- Saint Augustine |
_o__)  |
Ben Finney

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


Re: enumerate improvement proposal

2006-10-29 Thread Ben Finney
James Stroud <[EMAIL PROTECTED]> writes:

> Fredrik Lundh wrote:
> > why is it this function's job to add an offset to the actual
> > sequence index?
>
> The code is for an economist. She is insistent on starting with the
> first bin as 1.

Note that 'enumerate' is actually a built-in type, and 'enumerate()'
is the constructor returning a new object of that type.

A special case isn't special enough to change the built-in type.

>>> print enumerate("ABCDE")

>>> print list(enumerate("ABCDE"))
[(0, 'A'), (1, 'B'), (2, 'C'), (3, 'D'), (4, 'E')]

>> def obstinate_economist_enumerate(items):
... seq = [(i+1, x) for (i, x) in enumerate(items)]
... return iter(seq)
...
>>> print obstinate_economist_enumerate("ABCDE")

>>> print list(obstinate_economist_enumerate("ABCDE"))
[(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E')]

This doesn't produce an 'enumerate' object; if you really want that,
you could subclass 'enumerate', but it seems the above function does
what you want.

-- 
 \"I installed a skylight in my apartment. The people who live |
  `\  above me are furious!"  -- Steven Wright |
_o__)  |
Ben Finney

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


Re: enumerate improvement proposal

2006-10-29 Thread Georg Brandl
James Stroud wrote:
> I think that it would be handy for enumerate to behave as such:
> 
> def enumerate(itrbl, start=0, step=1):
>i = start
>for it in itrbl:
>  yield (i, it)
>  i += step
> 
> This allows much more flexibility than in the current enumerate, 
> tightens up code in many cases, and seems that it would break no 
> existing code. Yes, I have needed this behavior with enumerate, like 
> tonight and the current example. I put the "step" parameter in for 
> conceptual symmetry with slicing.
> 
> Here is a case use (or is it use case?):

Incidentally, I yesterday wrote a patch giving enumerate() a start parameter
(and, more importantly, changing it so that it doesn't wraparound at 
sys.maxint). It can be found here:

https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1586315&group_id=5470

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


Re: enumerate improvement proposal

2006-10-29 Thread Peter Otten
James Stroud wrote:

> I think that it would be handy for enumerate to behave as such:
> 
> def enumerate(itrbl, start=0, step=1):
>i = start
>for it in itrbl:
>  yield (i, it)
>  i += step
> 
> This allows much more flexibility than in the current enumerate,
> tightens up code in many cases, and seems that it would break no
> existing code. Yes, I have needed this behavior with enumerate, like
> tonight and the current example. I put the "step" parameter in for
> conceptual symmetry with slicing.
> 
> Here is a case use (or is it use case?):

I don' think you have a use case here:

# untested
def find_interval(value, bounds, funny_offset=0, reverse=False):
bounds = sorted(bounds)
if reverse:
index = len(bounds) - bisect.bisect_left(bounds, value)
else:
index = bisect.bisect_right(bounds, value)
return index + funny_offset

You can tell by its name which of the arguments I would have omitted :-)

> Of course, I haven't used step here. 

That seems to be typical. The only use case I've ever come across is start=1
for output aimed at a human reader.

> Even in this trivial example the 
> proposed enumerate cleans the code and logic, eliminating a couple of
> plus signs. For this real-world example, the practical requirement for
> reversing the bins obfuscates somewhat the de-obfuscation provided by
> the proposed enumerate. But I think that it might be obvious that the
> proposed enumerate could help significantly in cases a bit more
> complicated than this one.

Of course you get these claimed advantages from a self-written function,
too.

> Any thoughts?

You have my support for adding a start parameter to enumerate(). I fear it
won't make a difference.

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


Re: enumerate improvement proposal

2006-10-29 Thread James Stroud
Fredrik Lundh wrote:
> James Stroud wrote:
> 
>> The code is for an economist. She is insistent on starting with the 
>> first bin as 1.
> 
> leaky abstractions in reverse, in other words?  that's not a good design 
> approach.
> 
> 
>

I'm not sure I understand what "leaky abstractions" means.

I am helping someone with dubious programming skills make sense of a 
pile of code they wrote--code which getting a little unwieldy to debug. 
I think "design approach" can't really apply here. The idea is to make 
it comprehensible at some level.

I'm still curious what you mean by "leaky abstractions". Please explain.

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


Re: enumerate improvement proposal

2006-10-29 Thread Fredrik Lundh
James Stroud wrote:

> The code is for an economist. She is insistent on starting with the 
> first bin as 1.

leaky abstractions in reverse, in other words?  that's not a good design 
approach.



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


Re: enumerate improvement proposal

2006-10-29 Thread James Stroud
Fredrik Lundh wrote:
> James Stroud wrote:
> 
>> def enumerate(itrbl, start=0, step=1):
>>i = start
>>for it in itrbl:
>>  yield (i, it)
>>  i += step
> 
> that's spelled
> 
> izip(count(start), sequence)
> 
> in today's Python.
> 
>  > def in_interval(test, bounds, first=1, reverse=False):
> 
> why is it this function's job to add an offset to the actual sequence 
> index?
> 
> 
> 

BTW, thank you for your tip.

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


Re: enumerate improvement proposal

2006-10-29 Thread James Stroud
Fredrik Lundh wrote:
> why is it this function's job to add an offset to the actual sequence 
> index?
> 
> 

The code is for an economist. She is insistent on starting with the 
first bin as 1. I'm guessing, practically, binning linerizes data and 
the bin number may potentially become a divisor or perhaps the operand 
in a logarithm.

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


Re: enumerate improvement proposal

2006-10-29 Thread Fredrik Lundh
James Stroud wrote:

> def enumerate(itrbl, start=0, step=1):
>i = start
>for it in itrbl:
>  yield (i, it)
>  i += step

that's spelled

 izip(count(start), sequence)

in today's Python.

 > def in_interval(test, bounds, first=1, reverse=False):

why is it this function's job to add an offset to the actual sequence index?



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


Re: enumerate improvement proposal

2006-10-29 Thread James Stroud
James Stroud wrote:
> I think that it would be handy for enumerate to behave as such:
> 
> def enumerate(itrbl, start=0, step=1):
>   i = start
>   for it in itrbl:
> yield (i, it)
> i += step
> 
> This allows much more flexibility than in the current enumerate, 
> tightens up code in many cases, and seems that it would break no 
> existing code. Yes, I have needed this behavior with enumerate, like 
> tonight and the current example. I put the "step" parameter in for 
> conceptual symmetry with slicing.
> 
> Here is a case use (or is it use case?):
> 
> 
> # with the proposed enumerate
> import operator
> def in_interval(test, bounds, first=1, reverse=False):
>   op = operator.gt if reverse else operator.lt   # python 2.5
>   bounds = sorted(bounds, reverse=reverse)
>   for i, bound in enumerate(bounds, first):
> if op(test, bound):
>   return i
>   return i + 1
> 
> 
> # with the existing enumerate
> import operator
> def in_interval(test, bounds, first=1, reverse=False):
>   op = operator.gt if reverse else operator.lt   # python 2.5
>   bounds = sorted(bounds, reverse=reverse)
>   for i, bound in enumerate(bounds):
> if op(test, bound):
>   return i + first
>   return i + first + 1
> 
> 
> py> # eg
> ...
> py> in_interval(8, bounds)
> 2
> py> in_interval(1, bounds)
> 1
> py> in_interval(1, bounds, reverse=True)
> 5
> py> in_interval(8, bounds, reverse=True)
> 4
> py> in_interval(20, bounds, reverse=True)
> 2
> 
> Of course, I haven't used step here. Even in this trivial example the 
> proposed enumerate cleans the code and logic, eliminating a couple of 
> plus signs. For this real-world example, the practical requirement for 
> reversing the bins obfuscates somewhat the de-obfuscation provided by 
> the proposed enumerate. But I think that it might be obvious that the 
> proposed enumerate could help significantly in cases a bit more 
> complicated than this one.
> 
> Any thoughts?
> 
> James

After a brief reflection, I realized that I just described a 
"for-to-step-do" style loop one might find in many other languages, most 
notably BASIC.

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


enumerate improvement proposal

2006-10-29 Thread James Stroud
I think that it would be handy for enumerate to behave as such:

def enumerate(itrbl, start=0, step=1):
   i = start
   for it in itrbl:
 yield (i, it)
 i += step

This allows much more flexibility than in the current enumerate, 
tightens up code in many cases, and seems that it would break no 
existing code. Yes, I have needed this behavior with enumerate, like 
tonight and the current example. I put the "step" parameter in for 
conceptual symmetry with slicing.

Here is a case use (or is it use case?):


# with the proposed enumerate
import operator
def in_interval(test, bounds, first=1, reverse=False):
   op = operator.gt if reverse else operator.lt   # python 2.5
   bounds = sorted(bounds, reverse=reverse)
   for i, bound in enumerate(bounds, first):
 if op(test, bound):
   return i
   return i + 1


# with the existing enumerate
import operator
def in_interval(test, bounds, first=1, reverse=False):
   op = operator.gt if reverse else operator.lt   # python 2.5
   bounds = sorted(bounds, reverse=reverse)
   for i, bound in enumerate(bounds):
 if op(test, bound):
   return i + first
   return i + first + 1


py> # eg
...
py> in_interval(8, bounds)
2
py> in_interval(1, bounds)
1
py> in_interval(1, bounds, reverse=True)
5
py> in_interval(8, bounds, reverse=True)
4
py> in_interval(20, bounds, reverse=True)
2

Of course, I haven't used step here. Even in this trivial example the 
proposed enumerate cleans the code and logic, eliminating a couple of 
plus signs. For this real-world example, the practical requirement for 
reversing the bins obfuscates somewhat the de-obfuscation provided by 
the proposed enumerate. But I think that it might be obvious that the 
proposed enumerate could help significantly in cases a bit more 
complicated than this one.

Any thoughts?

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