What is below is a half-baked proposal for new built-in
Python operation. If anybody wants to raise this flag
again and fill gaps, please do so.
(I have not studied PEP howto much, so probably I missed
something important.)
I hope the idea of ".." is quite simple: make special syntactic
form for xrange (range). I am not into C to reference-implement this
feature, so if anybody could do it...
All in all, I think the feature is most wanted/useful by/for beginners.
---------------------------
PEP: ???
Title: Range Operation
Version: $Revision: 1.0 $
Author: r...@onego.ru (Roman Souzi), derived from tho...@xs4all.net (Thomas
Wouters)'s rejected PEP 204
Status:
Type: Standards Track
Python-Version: 2.0
Created:
Post-History:
Introduction
This PEP describes the `range operation' proposal for Python 2.?.
This PEP tracks the status and ownership of this feature, slated
for introduction in Python 2.?. It contains a description of the
feature and outlines changes necessary to support the feature.
This PEP summarizes discussions held in mailing list forums.
The feature is needed in Python because it allows beginners
to learn for loop before learning range/xrange functions
and adds more clarity to the program because of similarity
with mathematical notation.
List ranges
Ranges are sequences of numbers of a fixed stepping, often used in
for-loops. The Python for-loop is designed to iterate over a
sequence directly:
>>> l = ['a', 'b', 'c', 'd']
>>> for item in l:
... print item
a
b
c
d
However, this solution is not always prudent. Firstly, problems
arise when altering the sequence in the body of the for-loop,
resulting in the for-loop skipping items. Secondly, it is not
possible to iterate over, say, every second element of the
sequence. And thirdly, it is sometimes necessary to process an
element based on its index, which is not readily available in the
above construct.
For these instances, and others where a range of numbers is
desired, Python provides the `range' builtin function, which
creates a list of numbers. The `range' function takes three
arguments, `start', `end' and `step'. `start' and `step' are
optional, and default to 0 and 1, respectively.
The `range' function creates a list of numbers, starting at
`start', with a step of `step', up to, but not including `end', so
that `range(10)' produces a list that has exactly 10 items, the
numbers 0 through 9.
Using the `range' function, the above example would look like
this:
>>> for i in range(len(l)):
... print l[i]
a
b
c
d
Or, to start at the second element of `l' and processing only
every second element from then on:
>>> for i in range(1, len(l), 2):
... print l[i]
b
d
There are disadvantages with this approach:
- Clarity of notation: beginners need to remember function name,
its difference from xrange while other languages use syntactical
construct for the same purpose, not a function.
- what else?
The Proposed Solution
The proposed implementation uses new syntactic
entity to specify range operation, as shown below:
>>> for i in 1 .. 5:
... print i
1
2
3
4
5
Or in extended form to specify a step:
>>> for i in (1, 3) .. 5:
... print i
1
3
5
The new operation ".." generates xrange object
on by following rule:
a1 .. an
(a1, a2) .. an
is equivalent to:
xrange(a1, an+1[, a2-a1])
or other analog of xrange is that is applicable to the
type.
N.B. Operation ".." deviates from slice notations.
This is so in accordance with mathematical notation
of ranges.
There are no implicit forms of "..", that is, a1 and an must
be present.
To overload ".." operation in user-defined classes,
specific type must implement method
__range__(self, a1, an, a2=1). This method must return either
iterator object or a list.
In the table of operation priorities, .. operation must have less
(or equal) priority than lambda but more priority than
comma-separated display.
The implementation of range-literals will need changes
backward-compatible changes to built-in xrange() function
to allow calling __range__ if the type is not a built-in
object. (or is it already done?)
Otherwise, ".." is syntactical "sugar" for xrange().
Reference Implementation
".." is a binary operation which if the first argument is 2-tuple,
uses xrange() with 3 arguments (as shown above) and if it is
a 1-tuple or other object, then it evaluates xrange with two
arguments (step=1).
TODO. Anybody?
Open issues
- I'd liked to see 1, 3 .. n syntax instead of (1, 3) .. n, but
the later will interfere with comma-separated lists.
- How does will couple with iterators?
???
Copyright
This document has been based on the PEP 204 and is also
placed in the Public Domain.
------------------------
Sincerely yours, Roman A.Suzi
--
- Petrozavodsk - Karelia - Russia - mailto:r...@onego.ru -
> What is below is a half-baked proposal for new built-in
> Python operation. If anybody wants to raise this flag
> again and fill gaps, please do so.
> (I have not studied PEP howto much, so probably I missed
> something important.)
Just one thing: you should send it to Barry (ba...@wooz.org) at least if you
want it submitted as a real PEP :)
> I hope the idea of ".." is quite simple: make special syntactic
> form for xrange (range). I am not into C to reference-implement this
> feature, so if anybody could do it...
It's not too hard to do, though the syntax might require some fiddling. (the
'.' is currently eaten by the tokenizer as part of the number.) I could do
it myself, but I'm so busy right now, I think Tim has more time than I do
<0.4 wink>
> The proposed implementation uses new syntactic
> entity to specify range operation, as shown below:
> >>> for i in 1 .. 5:
> ... print i
> 1
> 2
> 3
> 4
> 5
I like, though the endpoint is debatable. Maybe Greg W. wants to do some
usage testing ? :)
> Or in extended form to specify a step:
> >>> for i in (1, 3) .. 5:
> ... print i
> 1
> 3
> 5
I don't like this. If anything, it should be the other way 'round
("1 .. (5, 3)") but even better would be something more obvious, such as
(1 .. 5) % 3
> The new operation ".." generates xrange object
> on by following rule:
I'd suggest it create an Iterator rather than an xrange object. Iterators
are new in the CVS tree, and will be in Python 2.2. Very neat things ;)
> There are no implicit forms of "..", that is, a1 and an must
> be present.
If .. created an iterator, it could be open-ended instead.
> Open issues
How about ranges of longs ? floats ? strings ? How about mixed types ?
--
Thomas Wouters <tho...@xs4all.net>
Hi! I'm a .signature virus! copy me into your .signature file to help me spread!
I think the syntax is clear enough to avoid discussions like
does-it-start-from-one-or-zero? Let the a..b syntax delimit the range
*including* both the minimum and maximum values. BTW it's pretty close to
the range syntax in other languages (such as Pascal, for enumerated
constants and sets).
> > Or in extended form to specify a step:
>
> > >>> for i in (1, 3) .. 5:
> > ... print i
> > 1
> > 3
> > 5
>
>I don't like this. If anything, it should be the other way 'round
>("1 .. (5, 3)") but even better would be something more obvious, such as
>
>(1 .. 5) % 3
This one is a little bit harder. Where did you take the 3 on the example
above? I could not understand the logic of '(1 .. 5) % 3'. I think that the
range operator should specify the step; something like '1 .. 5 % 2' is
clearer in my opinion. The use of '%' as 'step' operator is highly
debatable, though. Why not use any of the characters [!@#$&] ? <wink>
(if we keep going this way '%' is going to be the most overloaded operator
in the history of programming languages :-)
> > The new operation ".." generates xrange object
> > on by following rule:
>
>I'd suggest it create an Iterator rather than an xrange object. Iterators
>are new in the CVS tree, and will be in Python 2.2. Very neat things ;)
Agreed. In fact, xrange could be internally substituted by iterators.
As for other types of range constructors: in Pascal, you can use the syntax
above to construct ranges for enumerated types or sets. The catch is that
only scalar types can be used. This makes sense in Pascal, because the same
syntax is also used to specify sets. In Python, similarly, the same syntax
could be used (in the future) to implement set libraries. OTOH, ranges
built with floats may experience problems caused by the limited precision,
so that's a good reason to avoid it. Fixed point decimals don't suffer from
the same problems, though, and are a better candidate.
Carlos Ribeiro
One thing that comes to mind is the interpretation
of the endpoint. The syntax strongly suggests that the
endpoint is inclusive, as you propose. But this is
not the most useful meaning in Python. Most of the
time, range() is used in constructs such as
for i in range(len(mylist)):
which would become
for i in 0..len(mylist)-1:
The need to include the -1 is a nuisance and
potential source of error.
The alternative, making the endpoint exclusive,
would make the meaning of the .. construct
somewhat unintuitive.
--
Greg Ewing, Computer Science Dept, University of Canterbury,
Christchurch, New Zealand
To get my email address, please visit my web page:
http://www.cosc.canterbury.ac.nz/~greg
> Agreed. In fact, xrange could be internally substituted by iterators.
No, it could not. xrange(1,10)[3] works, iter(range(1,10))[3] does not:
>>> xrange(1,10)[3]
4
>>> iter(range(1,10))[3]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsubscriptable object
>>>
xrange isn't an iterator, it's a 'generator' (or a 'lazy list'). I agree
that xrange should adhere to the iteration protocol, but making it *just* an
iterator isn't enough.
>If you want to get this considered, you'll have to
>make sure your PEP explicitly addresses all the reasons
I read them and found that almost all of them are caused
by using slice-like notation.
There are no more reasons to reject ".." than there are
reasons to obsolete range/xrange, because its just
a more newbie-frienly way to write them.
>for the rejection of PEP 204. (That might not be easy,
>since the rejection notice attached to PEP 204 is
>rather sketchy!)
I understand the rejection very well:
":" notation is very overused by the PEP 204.
(makes to much confusion).
IMHO, it's the main reason for Guido to reject it.
>One thing that comes to mind is the interpretation
>of the endpoint. The syntax strongly suggests that the
>endpoint is inclusive, as you propose. But this is
>not the most useful meaning in Python.
The reason under Python incl-excl nature is that
these are intermediate points, needed for slice-operations
to be natural like in:
a[0:0] = [1,2,3]
There is no reason to bring this into ".." notation, because
its different from ":" even visuall and it is more naturally
to use convenient incl-incl ranges.
Most of the
>time, range() is used in constructs such as
>
> for i in range(len(mylist)):
These must be eliminated by use of maps, apply, etc -
by functional style.
>which would become
>
> for i in 0..len(mylist)-1:
>
>The need to include the -1 is a nuisance and
>potential source of error.
>
>The alternative, making the endpoint exclusive,
>would make the meaning of the .. construct
>somewhat unintuitive.
I agree.
The fact, that there will be TWO ways for ranges doesn't
bother me, because the reason to include ".." into
Python is allowing beginners to appreciate more naturally
looking code than range(1,101).
I even think there is a need to rename ".." from range operation
to something other.
Sincerely yours, Roman Suzi
--
_/ Russia _/ Karelia _/ Petrozavodsk _/ r...@onego.ru _/
_/ Wednesday, May 09, 2001 _/ Powered by Linux RedHat 6.2 _/
_/ "Always remember no matter where you go, there you are." _/
>On Tue, May 08, 2001 at 07:49:17PM -0300, Carlos Ribeiro wrote:
>
>> Agreed. In fact, xrange could be internally substituted by iterators.
>
>No, it could not. xrange(1,10)[3] works, iter(range(1,10))[3] does not:
>
>>>> xrange(1,10)[3]
>4
>>>> iter(range(1,10))[3]
>Traceback (most recent call last):
> File "<stdin>", line 1, in ?
>TypeError: unsubscriptable object
>>>>
>
>xrange isn't an iterator, it's a 'generator' (or a 'lazy list'). I agree
>that xrange should adhere to the iteration protocol, but making it *just* an
>iterator isn't enough.
I think, ".." will be just another way to write xrange.
If it ever will be an iterator - so will be "..".
Or it could be some yet-to-implement irange, which
can be read as "inclusive range" or "iterator-creating range"
-- this must not stop from proposing ".." notation now.
This small feature will make Python's for loops much
friendlier to beginners.
I do not fear
for i in 0..len(mylist)-1
because this is _explicit_ writing of the fact mylist
is indexed from 0. If there will be errors, they will
cause IndexErrors and not some subtle logical errors.
for x in seq[a:b]:
print x
versus
for i in a..b:
print seq[i]
My own intuition would expect the same behavior
from these two loops. I would consider it VERY
unintuitive to have them behave differently!!!
Maybe this should be accepted and reinforced
with a different syntax for the range, e.g.
for i in [a:b]:
print seq[i]
with the existing brackets-and-colons tokens
in lieu of the new proposed '..' token. Now
the fact that b is excluded, just as in s[a:b],
should perhaps be even more obvious...?
Alex
>>(1 .. 5) % 3
>
> This one is a little bit harder. Where did you take the 3 on the
> example above? I could not understand the logic of '(1 .. 5) % 3'. I
> think that the range operator should specify the step; something like
> '1 .. 5 % 2' is clearer in my opinion. The use of '%' as 'step'
> operator is highly debatable, though. Why not use any of the characters
> [!@#$&] ? <wink>
>
Why not add a 'step' method to iterators and sequence types?
step(self, step, start=0)
Returns a new iterator or sequence containing every 'step'
value from index 'start' in the original sequence.
For iterators this would return a new iterator, for sequences it would
return a new sequence. If you want a step iterator from a sequence you just
have to do: iter(sequence).step(n)
So:
>>> range(1, 11).step(2)
[1, 3, 5, 7, 9]
>>> (1..10).step(2)
<some iterator type returning 1, 3, 5, 7, 9 successively>
>>> range(1, 11).step(2, 1)
[2, 4, 6, 8, 10]
>>> lst = range(1, 11)
>>> zip(lst.step(2), lst.step(2, 1))
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
--
Duncan Booth dun...@rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?
I disagree. Inclusive-lower-bound, exclusive-upper-bound
is a VERY important and useful idiom, which we should
strive to make as widespread as we possibly can: by the
very fact of being invariably used everywhere lower and
upper bounds are specified, it helps a LOT against
off-by-one errors! I first saw it explained in Koenig's
excellent "C traps and pitfalls" book, by the way.
Python does it pretty well today:
for item in seq[lower:upper]:
print item
and
for index in range(lower,upper):
print seq[index]
behave the same way, just as they should. If instead:
for index in lower..upper:
print seq[index]
did behave differently, I would could that as a very
serious inconsistency in the language. I believe it
would induce many off-by-one errors in apparently
unrelated situations, such as slices, in newbies, as
well as being a nasty tripwire for experienced users.
Alex
That is far from being the only reason!
> There is no reason to bring this into ".." notation, because
> its different from ":" even visuall and it is more naturally
> to use convenient incl-incl ranges.
"convenience" is probably the excuse brought for the worst
pieces of software design today, although the older one of
"optimization" is still going strong.
Upper-bound-excluded ranges are in fact more convenient, and
help avoid off-by-one errors. Having DIFFERENT behavior
between seq[a:b] and [seq[x] for x in a..b] would, moreover,
be PARTICULARLY horrid.
> >time, range() is used in constructs such as
> >
> > for i in range(len(mylist)):
>
> These must be eliminated by use of maps, apply, etc -
> by functional style.
s/must/may often/. Iterating over a range of indices
will remain an important idiom even when a newbie has
fully digested map and apply. For example, often we
need to operate on items in a sequence depending on
the item that comes immediately before or after. To
say that the approach of zipping the sequence to its
"shifted" copy "must", or even "should", eliminate the
simple and obvious approach of index-loops smacks of
very substantial hubris.
For example, let's say we need the sequence of all
characters that come right after a '!' in string s.
Zip-approach:
def afterbang1(s):
result = []
for previous, thisone in zip(s, s[1:]):
if previous == '!':
result.append(thisone)
return result
versus index-approach:
def afterbang2(s):
result = []
for i in range(1,len(s)):
if s[i-1] == '!':
result.append(s[i])
return result
versus keep-state approach:
def afterbang3(s):
result = []
previous = s[0]
for c in s[1:]:
if previous == '!':
result.append(c)
previous = c
return result
versus "map, apply, etc" approach:
def afterbang4(s):
return map(lambda x,y: y,
filter(lambda x,y: x=='!',
map(None, s[:-1], s[1:])))
Personally, I find afterbang2 clearest, and
therefore best. If concision is a goal, the
first two approaches can easily be rewritten
as list comprehensions, of course:
Zip-approach with LC:
def afterbang1_LC(s):
return [ thisone
for previous, thisone in zip(s, s[1:])
if previous == '!' ]
versus index-approach with LC:
def afterbang2_LC(s):
return [ s[i]
for i in range(1, len(s))
if s[i-1] == '!' ]
Again, it's a subtle matter of taste between
these two, but I think the second one is better.
I definitely wouldn't mind having a
for i in 1..len(s)
alternative to use in afterbang2 and 2_LC,
but I'd never consider having to use
for i in 1..len(s)+1
as even remotely approaching acceptability.
> >The alternative, making the endpoint exclusive,
> >would make the meaning of the .. construct
> >somewhat unintuitive.
>
> I agree.
I don't.
> The fact, that there will be TWO ways for ranges doesn't
> bother me, because the reason to include ".." into
> Python is allowing beginners to appreciate more naturally
> looking code than range(1,101).
Getting beginners used to inclusive-upper-end idioms
and then having them trip over exclusive-upper-end
ones elsewhere later is NOT doing them any favour.
Alex
Ok, I'm in brainstorm mode. You're warned :-) Some weird ideas are just
popping out of my mind:
1) Have both ':' and '..' as range operators. ':' excludes the last
element, '..' includes it. This is a very simple rule-of-thumb. A beginner
may be confused, but it's not something hard to learn.
2) Force the construct to be specified inside brackets or parenthesis,
pretty much like list comprehensions.
3) If (2) is approved, then the step operator becomes a natural extension
of the list comprehension syntax:
>>> [1..5 step 2]
[1,3,5]
>>> [1:5 step 2]
[1,3]
It's clear, readable and unambiguous.
Carlos Ribeiro
I think it might be -- I see no graphical suggestion of the
behavior differences.
> 2) Force the construct to be specified inside brackets or parenthesis,
> pretty much like list comprehensions.
I like the ideas of brackets for that.
for i in [a:b]
just looks so neat...:-).
> 3) If (2) is approved, then the step operator becomes a natural extension
> of the list comprehension syntax:
>
> >>> [1..5 step 2]
> [1,3,5]
> >>> [1:5 step 2]
> [1,3]
>
> It's clear, readable and unambiguous.
Sure does. I wonder if 'step' would have to become a keyword here
(presumably a no-go) or if it could be "fudged" the way non-keyword
"as" was added to import and from statements.
Alex
for i in [0:10]:
print i
Thomas
>At 12:23 09/05/01 +0200, Alex Martelli wrote:
>>Getting beginners used to inclusive-upper-end idioms
>>and then having them trip over exclusive-upper-end
>>ones elsewhere later is NOT doing them any favour.
>
>Ok, I'm in brainstorm mode. You're warned :-) Some weird ideas are just
>popping out of my mind:
>
>1) Have both ':' and '..' as range operators. ':' excludes the last
>element, '..' includes it. This is a very simple rule-of-thumb. A beginner
>may be confused, but it's not something hard to learn.
I agree.
>
>2) Force the construct to be specified inside brackets or parenthesis,
>pretty much like list comprehensions.
This is what rejected PEP 204 is about...
>3) If (2) is approved, then the step operator becomes a natural extension
>of the list comprehension syntax:
>
> >>> [1..5 step 2]
>[1,3,5]
> >>> [1:5 step 2]
>[1,3]
>
>It's clear, readable and unambiguous.
Well, I do not pretend (1, 2) .. 5 is the only way.
But "a .. b step c" is too... verbose.
>Carlos Ribeiro
If all we want to do is get rid of
for i in range(len(seq)):
...
why not overload range so it can take a sequence directly:
for i in range(seq):
...
If we really want range literals (which I don't see as particularly useful
outside this application although I'm happy to be proven wrong <wink>), we
can't use x:y since Guido has allready nixed it, and we shouldn't use x..y
since the established meaning interfers with common usage leading to
unappealing constructs like 0..len(seq)-1. We could certainly come up with
other syntax, e.g. x -> y meaning from x up to, but not including, y:
for i in 0 -> len(seq):
...
I still favor overloading range though...
-- bjorn
Since this is standard math notation for ranges, with : substituted for ,
to avoid syntax conflict, I like it the best of all proposals in this
thread. A step value, is present, could go either in middle or end.
I would really like to perform set operations in Python. Some good
libraries already provide support for this (kjBuckets comes to mind). The
a..b syntax is a nice way to specify arbitrary set constants, such as in:
if some_number in [1..3,7..9]:
do_something()
There are several uses for constructs like the one above. I keep thinking
that '..' is clearly inclusive, so why not give it a try?
Carlos Ribeiro
I favor leaving Python as-is, since this entire thread is about solving a
non-problem. If you want a shorter way of writing 'range(len(x))', you can
always write your own function. If there is really a need of such a
function in '__builtin__', I would prefer that it have a new name. How
about 'indexes'?
--
Rainer Deyke (ro...@rainerdeyke.com)
Shareware computer games - http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor
Please, recall the main reason for the new feature:
- to allow beginners learn loops BEFORE they learn
lists and functions (which are needed now to explain
for-loop).
Even recursion could be explained without lists in Python,
why for-loops need this prerequisite?
It is not too expensive to write range(a,b,c) or
something similar, but cp4e needs cleaner way to do for loops.
If not ".." syntax, then any other, but with EXPLICIT
mentioning of the including/excluding nature of
ranges.
eg
for i from 1 to 10
for i from 1 before 11
for j from 1 to 100 step 2
-- these could be also used in list comprehensions consistently:
[i for i from 1 to 10]
*
But our discussion showed that there is probably no
much need in pushing ".." any more... :-(
because I see ".." as an only-for-novice feature
and we (who discuss) are no novices to judge...
Something like that can already be done without introducing
new syntax, as in
>>> import types
>>> class Set:
... def __getitem__(self, terms):
... data = []
... for term in terms:
... if type(term) == types.SliceType:
... for x in range(term.start, term.stop):
... data.append(x)
... else:
... data.append(term)
... return data
...
>>>
>>> Set = Set()
>>> Set[1:3, 7:9]
[1, 2, 7, 8]
>>> Set[1, 4:10]
[1, 4, 5, 6, 7, 8, 9]
>>>
Andrew
da...@acm.org
(And if it were to exist, which it shouldn't, Alex is right that it
*has* to be a semi-closed interval. Anything else would be an
abomination.)
|>oug
done much python training lately, or are you just making
things up as you go?
(in my experience, you don't have to understand much
about functions and lists to learn how to *use* range in
simple for-in loops...)
Cheers /F
> I like the ideas of brackets for that.
> for i in [a:b]
> just looks so neat...:-).
That was the subject of PEP 204 (Range Literals) which was rejected.
I don't know why. (the stated open issues should simply all be
answered with: "no magic!").
It seems to me that it would be rather neat to extend the list
comprehension idea to be able to create an iterator rather than a
list. I shudder at the idea of proposing syntax for that, but using
[| ... |] instead of [ ... ] might work.
Now excuse me while I run for cover... :-)
--
Dr. Denys Duchier Denys....@ps.uni-sb.de
Forschungsbereich Programmiersysteme (Programming Systems Lab)
Universitaet des Saarlandes, Geb. 45 http://www.ps.uni-sb.de/~duchier
Postfach 15 11 50 Phone: +49 681 302 5618
66041 Saarbruecken, Germany Fax: +49 681 302 5615
Isn't more pythonic the recipe (i think it is from Alex):
for i, a in Indexed(seq):
...
where indexed is just:
class Indexed:
def __init__(self, seq):
self.seq = seq
def __getitem__(self, i):
return i, self.seq[i]
? Do we really need syntatic changes (..) and semantic changes also? Doesn't
things like '..' make the language more difficult to learn for begginners?
The reference manual must be bigger and bigger with each addition of this
kind. Other changes, like the elimination of the type/class differences make
the manual smaller. I think these are the things to be focused on.
Regards:
Walter
--
--------------
Walter Moreira <> Centro de Matematica <> Universidad de la Republica
email: wal...@cmat.edu.uy <> HomePage: http://www.cmat.edu.uy/~walterm
+-----------------------------------------------------
/OD\_ | Contrary to popular belief, Unix is user friendly.
O o . |_o_o_) | It just happens to be very selective about who its
| friends are. -- Kyle Hearn
--+--
like we did with those pesky macros, you mean?
Cheers /F
> > Why don't we just nip this creeping-featurism in the bud and just say
> > "no" to a new range syntax.
> like we did with those pesky macros, you mean?
Yup, except that I think "we" should think more carefully about the
difference between powerful abstraction mechanisms and
creeping-featurism. The former helps prevent the latter.
(Besides, I never lobbied for Python to include macros. I only stated
that it would be a better language if it had them. But sometimes
better is worse.)
|>oug
|>oug
> Speaking of creeping-featurism, how come we have list comprehension,
> but not tuple comprehension? Seems inconsistent to me.
A list contains a variable number of homogeneous values, e.g. the
lines of a file. Lists are like arrays in other languages. A tuple
contains a fixed number of heterogeneous values where each element has
a distinct meaning e.g. (year, month, day) for a date. Tuples are
like data structures or product types in other languages, except that
their types and fields are nameless. Comprehensions work with a
variable number of homogeneous values, so they produce lists.
--
Any opinions expressed are my own and not necessarily those of Roundpoint.
> A list contains a variable number of homogeneous values, e.g. the
> lines of a file.
Homogeneousness isn't required, though I'd expect it's how they're
often used.
Well, there would be a simple way to make ranges that conformed to both. Use
the mathematical notation for describing inclusive and exclusive bounds
(although it would be using '..' instead of ',').
If I remember correctly ...
[0..10] - range is 0 to 10
[0..10) - range is 0 to 9
(0..10] - range is 1 to 10
(0..10) - range is 1 to 9
There - everyone is happy, and an unadorned 0..10 is an error.
This has the advantage of looking more like a sequence as well.
It also has the disadvantage that it may not be immediately obvious to
someone what the range is - '(' and '[' aren't *that* dissimilar when right
near each other.
The other consideration is how this would work with steps. Perhaps
overloading ':' here would work, since 0..10 unadorned would be invalid ...
[0..10:3] - range is 0 to 10, step 3
(10..0:-2] - range is 9 to 0, step -2
Anyway, I'm sure there are lots of objections to this, but I'd like to hear
them :)
Tim Delaney
> Douglas Alan <nes...@mit.edu> writes:
> > Speaking of creeping-featurism, how come we have list comprehension,
> > but not tuple comprehension? Seems inconsistent to me.
> A list contains a variable number of homogeneous values, e.g. the
> lines of a file. Lists are like arrays in other languages. A tuple
> contains a fixed number of heterogeneous values where each element
> has a distinct meaning e.g. (year, month, day) for a date.
I think you have some other language in mind, rather than Python. In
Python, the only semantic difference between a list and a tuple is
that a tuple is immutable.
> Tuples are like data structures or product types in other languages,
> except that their types and fields are nameless. Comprehensions
> work with a variable number of homogeneous values, so they produce
> lists.
filter() on a tuple returns a tuple. The length of the tuple cannot
be known in advance. map(), on the other hand, always returns a list.
But map can take multiple sequence arguments, so it wouldn't always be
obvious to know which type of sequence to duplicate. I suppose the
same is true for comprehension. But, it seems to me that Python could
allow
(x*2 for x in t)
to make a tuple as easily as it allows
[x*2 for x in l]
to make a list.
|>oug
Who says we don't?
tuple([2*i for i in [1,2,3]])
:-)
--
Greg Ewing, Computer Science Dept, University of Canterbury,
Christchurch, New Zealand
To get my email address, please visit my web page:
http://www.cosc.canterbury.ac.nz/~greg
But that's exactly what PEP 204 proposed, and
Guido rejected it.
(The PEPs are supposed to record such decisions
so that these discussions don't keep recurring.
But that only works if people read the PEPs. :-)
Maybe we need a bot that posts all the rejected
PEPs to c.l.py every month? :-) :-)
I don't see anything wrong with learning about
lists before for-loops. Playing with lists is
much more fun than just playing with numbers
(which non-mathematically-inclined people may
find boring).
And functions don't come into it at all,
either way.
> But our discussion showed that there is probably no
> much need in pushing ".." any more... :-(
> because I see ".." as an only-for-novice feature
> and we (who discuss) are no novices to judge...
More importantly, I don't think there should be
any syntax that is there *just* for novices. A
piece of syntax needs to earn its keep much better
than that before it's worth keeping around.
>"Bjorn Pettersen" <BPett...@NAREX.com> wrote in message
>news:mailman.989423654...@python.org...
>> for i in 0 -> len(seq):
>> ...
>>
>> I still favor overloading range though...
>
>I favor leaving Python as-is, since this entire thread is about solving a
>non-problem.
The problem is not to make range(len(seq)) shorter, but
to make for loop easier to learn:
right now FUNCTIONS and LISTS are needed to understand
for loop. (Even recursion is "easier" with just FUNCTIONS
to know ;-)
So, I started the thread to:
1. Discuss if the raised problem is "no problem"
2. If the 1. is not true, to discuss syntactic solution.
We seem to drift to no. 2 without questioning no. 1.
>If you want a shorter way of writing 'range(len(x))', you can
>always write your own function. If there is really a need of such a
>function in '__builtin__', I would prefer that it have a new name. How
>about 'indexes'?
Sincerely yours, Roman Suzi
This proposed notation (and you aren't the first to propose it) would be
bizarrely misunderstood by newcomers. I certainly don't want to have to
explain that the same object can be described in four different ways, and
suggest when [1..9] is more appropriate than (0..10) is more appropriate
than [1..10) is more appropriate than (0..9].
So, why have four representations for the same thing?
there-should-be-one-obvious-way-to-do-it-ly y'rs - steve
for dir in sys.path:
print dir
regards
STeve
> Roman Suzi wrote:
> > Please, recall the main reason for the new feature:
> >
> > - to allow beginners learn loops BEFORE they learn
> > lists and functions (which are needed now to explain
> > for-loop).
> >
> > Even recursion could be explained without lists in Python,
> > why for-loops need this prerequisite?
>
> done much python training lately, or are you just making
Yes. I taught programming classes a year ago.
That is where I had some trouble with for-loops.
> things up as you go?
>
> (in my experience, you don't have to understand much
> about functions and lists to learn how to *use* range in
> simple for-in loops...)
>
> Cheers /F
Sincerely yours, Roman A.Suzi
--
- Petrozavodsk - Karelia - Russia - mailto:r...@onego.ru -
> > Well, there would be a simple way to make ranges that
> conformed to both.
> Use
> > the mathematical notation for describing inclusive and
> exclusive bounds
> > (although it would be using '..' instead of ',').
> >
> > If I remember correctly ...
> >
> > [0..10] - range is 0 to 10
> > [0..10) - range is 0 to 9
> > (0..10] - range is 1 to 10
> > (0..10) - range is 1 to 9
> >
> Correct me if I'm wrong, but don't the concepts of open and
> closed intervals
> belong to analysis and not discrete mathematics -- in other
> words, they
> apply to infinite sets but not finite ones. An open interval
> (x,y) is the
> set of all numbers strictly greater than x and strictly less than y.
> Dedekind will be turning in his grave...
Well, there are *no* infinite sets in computing, so it's not generally
applicable here (the largest long integer in Python for example must be
bound by the amount of memory available to the Python process).
That may well be true (been a few years since I've done any formal maths
work/study), however it is fine system (which is an infinite set) 9 is the
greatest integer strictly less than 10.
It's is perfectly valid to define the set you are using - this notation
would only be valid for the set of integers (including long integers
naturally).
> This proposed notation (and you aren't the first to propose
> it) would be
> bizarrely misunderstood by newcomers. I certainly don't want
> to have to
> explain that the same object can be described in four
> different ways, and
> suggest when [1..9] is more appropriate than (0..10) is more
> appropriate
> than [1..10) is more appropriate than (0..9].
>
> So, why have four representations for the same thing?
Again, I personally agree ... you may have noticed my comment "There -
everyone is happy" ... ;) OTOH, I think inclusive lower-bound, optional
inclusive upper bound i.e. [] and [) would be useful. Having optional
exclusive lower bound was just a bit of fun.
Also, remember that it is quite possible to create a range counting down ...
in some cases I could see exclusive lower bound, inclusive upper bound being
useful (except that's really ex upper, in lower, but in reverse ...).
Tim Delaney
and you don't think you can adjust the training material to cover
lists and functions briefly (from a use, don't create perspective)
before going into details about what for-in really does?
adding inconsistencies to the language to work around a problem
someone once had when explaining the current situation doesn't
sound that appealing...
Cheers /F
Personally, I've found that for-loops can easily
be taught without having introduced lists yet,
because they work on ANY sequence -- and a datatype
you will surely have introduced VERY early in any
Python course is "string"! A string is a sequence.
This is of limited (though non-null) usefulness in
most Python use, but it SURE comes in handy when
teaching Python to a totally-raw beginner...:
"""
For example, let's print the vowels, only, from
the string the user has introduced. This is easy
because we can look at any string one character
at a time with the for statement.
astring = raw_input("Please enter a string: ")
print "Vowels:",
nvowels = 0
for c in astring:
if c in 'aeiouAEIOU':
print c,
nvowels = nvowels + 1
print
print nvowels,"vowels in total"
if nvowels:
print "The last vowel was",c
"""
then you can go on to explain break, for/else,
and so on, all based on this simple toy example
about looping character by character on a string.
I do think one probably needs to have introduced
raw_input, strings, integers, assignment,
print, and if, before loops can fruitfully be
presented to a raw beginner. But having some
nice special syntax for range literals would not
alter that, it seems to me. Lists, if you wish,
can still come later, anyway.
Alex
Didn't you write "Python should have procedural macros like Lisp."
(on 2001-04-16 14:20:05 PST -- google doesn't make it easy to give
other and more precise message identification)?
"Lobbying" no doubt connotes much more and better organized effort
than just posting netnews messages. But you didn't just state that
Python would be a better language if it had macros: you did write it
*SHOULD* have them (nor did I ever read anything from you to the
tone of "sorry, I was wrong, it SHOULDN'T have them" -- lots that
might be interpreted as attempts at backing off without actually
doing so, but never any apology or retraction).
Just to clarify by analogy and example: I opine, for example, that
Python would be a (marginally) better language if it didn't have
`expression` as a shorthand for repr(expression) -- it's one extra
(little) piece of syntactic baggage which IMHO is not "carrying
its weight". But from this opinion does not follow that Python
*shouldn't* have `expression` -- that would be quite a stronger
assertion (personally, there is exactly one construct in Python
today of which I feel I could assert Python "shouldn't have it").
Alex
There is no demand for syntactically supported ranges?
> "Roman Suzi" <r...@onego.ru> wrote in message
> news:mailman.989472800...@python.org...
> ...
> > > > Even recursion could be explained without lists in Python,
> > > > why for-loops need this prerequisite?
> > >
> > > done much python training lately, or are you just making
> >
> > Yes. I taught programming classes a year ago.
> > That is where I had some trouble with for-loops.
>
> Personally, I've found that for-loops can easily
> be taught without having introduced lists yet,
> because they work on ANY sequence -- and a datatype
> you will surely have introduced VERY early in any
> Python course is "string"! A string is a sequence.
> This is of limited (though non-null) usefulness in
> most Python use, but it SURE comes in handy when
> teaching Python to a totally-raw beginner...:
Thank you Alex! This idea have not occured to me
(about strings as sequences instead of lists).
Yes, I think it would be a nice addition, and I'm sure we're not alone -
many people on the group contributed with ideas on this topic. While I
understand that there are some issues with the proposal - including or
excluding the upper limit, using braces to delimit the range, or how to
specify the step operator - I believe that the concerns are mostly in the
reaction-to-change field.
So, if we can propose a new syntax that:
- is clear for both novices and experienced Python programmers
- does not break anyone's code
- is consistent with related features (slicing and list comprehensions)
... there will be no real reason not to make it.
p.s. I was one of the guys that wrote about 'creeping featurism' a few
months ago. I don't think that it is a good idea, and many PEPs were really
weird. Now, this seems to be a very simple addition to me, because we can
meet the three criteria above. I'm happy to be proved wrong, but please,
let's talk about facts, not emotions, ok?
Carlos Ribeiro
Only if you don't value simplicity. If this is the case, why are you using
Python at all?
--
Rainer Deyke (ro...@rainerdeyke.com)
Shareware computer games - http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor