python for loop

S

Steven D'Aprano

Dragging this back to the original topic, you clearly find starting list
indices from zero unintuitive. To me, with a mathematical background,
it's not just intuitive, it's correct. All sorts of useful properties
fall out from that, not the least of which is the fact that
"a[0:len(a)]" slices the whole of a list.

But some non-useful properties fall out of that too.

Want the fifth item? a[5] gives you the *sixth* item, which is weird, so
you have to use a[5-1] to get the fifth item.

There is a major clash between the names of ordinals in human languages
and zero-based counting. In human languages, the Nth-ordinal item comes
in position N. You can keep that useful convention with zero-based
counting by inventing the ugly word "zeroth", but that just leads to
bizarro-talk like "the zeroeth item comes first, the first item comes
second, and so on".

a[0:len(a)] is legal, a[0] is legal, but surprisingly a[len(a)] is an
error.

Despite coming from a Pascal background, I've come to appreciate and
prefer zero-based indexing for programming. But I'm not blind to the
disadvantages. I'll often work out an algorithm using pencil and paper
and counting from one, and then subtract one to get zero-based indexes.

There are advantages and disadvantages to both systems, but on balance, I
think that zero-based is a better system for programming, and one-based
for natural language.
 
D

Dave Angel

Natural language is full of ambiguity, which is why my parents used to
argue about the meaning of "next Wednesday," or of "the next exit."
Until you have a starting reference, and until you decide whether it's a
closed or open interval, you can't be sure everyone will get the same
semantics. Because of their bickering 50 years ago, I try to use a
longer phrase, such as "the Wednesday a week from today" or "exit 52."

In most? of Europe, the first floor is the one you get to after you go
up one flight of stairs. In the US, first floor is usually the ground
floor.

My ruler starts at zero, and has an explicit zero on it. Most rulers
start the same way, but don't actually show the zero. But if you had a
ruler that started with one, you'd end up with some off-by-one errors.

I repeatedly see people think that if Joe has $100, and Mary has three
times more, that she has $300. Yet these same people would balk at the
notion that 10% more would be $10.

English is a funny language (as I suspect most languages are), and full
of ambiguities and foolish inconsistencies. Having worked with some 35
languages over 35 years in the industry, I was glad that most of them
were zero based.
Dragging this back to the original topic, you clearly find starting list
indices from zero unintuitive. To me, with a mathematical background,
it's not just intuitive, it's correct. All sorts of useful properties
fall out from that, not the least of which is the fact that
"a[0:len(a)]" slices the whole of a list.

But some non-useful properties fall out of that too.

Want the fifth item? a[5] gives you the *sixth* item, which is weird, so
you have to use a[5-1] to get the fifth item.

There is a major clash between the names of ordinals in human languages
and zero-based counting. In human languages, the Nth-ordinal item comes
in position N. You can keep that useful convention with zero-based
counting by inventing the ugly word "zeroth", but that just leads to
bizarro-talk like "the zeroeth item comes first, the first item comes
second, and so on".

a[0:len(a)] is legal, a[0] is legal, but surprisingly a[len(a)] is an
error.

Despite coming from a Pascal background, I've come to appreciate and
prefer zero-based indexing for programming. But I'm not blind to the
disadvantages. I'll often work out an algorithm using pencil and paper
and counting from one, and then subtract one to get zero-based indexes.

There are advantages and disadvantages to both systems, but on balance, I
think that zero-based is a better system for programming, and one-based
for natural language.
 
B

bearophileHUGS

Lada Kugis:
(you have 1 apple, you start counting from 1 ...<

To little children I now show how to count starting from zero: apple
number zero, apple number one, etc, and they find it natural
enough :)

Bye,
bearophile
 
S

Steven D'Aprano

Lada Kugis:

To little children I now show how to count starting from zero: apple
number zero, apple number one, etc, and they find it natural enough :)


Ah, but that's not the same as counting ordinals from zero. Consider the
difference between an empty list, which has zero items, and a list of
length one, which as that item in position zero.

The empty list [] clearly has zero items, in zero "bins", so the bins
aren't numbered.

A list with one item [x] has one bin, labelled "Index 0".
A list with two items [x, y] has two bins, labelled Index 0 and Index 1.
A list with three items [x, y, z] has three bins, labelled Index 0, Index
1 and Index 2.
etc.

Counting "No apples plus one apple makes one apple" is easy enough. But
pointing to an apple clearly there and saying "Let's call that apple
number zero, even though there is one apple", that requires a very
special child!
 
T

Tim Rowe

2009/4/1 Carl Banks said:
I am also an engineer, and I can tell your idea of intuitive is not
universal, even among engineers.  I certainly do not lean toward one-
based indexing.

Another engineer here who finds 0-based indexing more intuitive than
1-based indexing.
 
L

Lou Pecora

Lada Kugis said:
steven, thanks for answering,

yes, i saw the second one a little time ago (someone else posted it as
well in really cute handwriting version :) and the first time just
now, but the examples which both of them give don't seem to me to be
that relevant, e.g. the pros don't overcome the cons.

imho, although both sides (mathematical vs engineer) adress some
points, none of them give the final decisive argument.
i understand the math. point of view, but from the practical side it
is not good. it goes nicely into his tidy theory of everything, but
practical and intuitive it is not. as i said, being an engineer, i
tend towards the other side, so this is biased opinion (nobody can be
unbiased) but from a practical side it seems unpractical for
engineering problems (and to me, the purpose of computers is to help
humans to build a better world, not to prove theories - theories are
useless if they don't help us in reality. so we should try to adapt
computing to real world, not our world to computers).

There is nothing more practical than a good theory.
--- James Clerk Maxwell

You said you came from the C world (besides Fortran). If so, you have
already seen array indexing starting with 0 and going to n-1.

Why, then, should Python be so foreign to you?
 
L

Lada Kugis

Lada,

I am also an engineer, and I can tell your idea of intuitive is not
universal, even among engineers. I certainly do not lean toward one-
based indexing.

From a programming standpoint--and remember Python is a programming
language--zero-based indexing eliminates the need for a whole lot of
extra +1s and -1s when indexing, slicing, and iterating, a lot more
than it causes, and that is worth the "cost". This might not be
apparent to you if you never tried seriously taking advantage of
indexing from zero, or if your programming experience is very narrow.
These both seem to be true for you, so you'll just have to take my
word for it.


You have repeated several cs based points already stated. But apart
from a programming standpoint - could you give a few examples, where
"on paper" (as to avoid stepping into "programmer's territory") zero
indexing could be more intuitive ?
(of course, taking into account your previous based calculations,
which are based on 1 indexing - I imagine you still use matrices with
a11 as a first element)

Lada
 
L

Lou Pecora

and
the (m-n) point Chris was trying to explain doesn't seem that relevant
to me.

That's because you haven't done enough programming really using the
Python structures and objects. You can really do a lot with lists and
tuples. When you do you will see Chris' point emphatically.
 
L

Lada Kugis

There are advantages and disadvantages to both systems, but on balance, I
think that zero-based is a better system for programming, and one-based
for natural language.

Nicely put.

Yes, along with some of your other arguments, I think I can agree that
this sums it up best. I'll just have to adapt myself to natural
language thinking at one side, and programming thinking at the other.



Lada
 
M

MRAB

Lada Kugis wrote:
[snip]
Yes, that's it. I won't argue over it, since I can't change it, but 1
is still more natural to me (it is "the real world" way). The above
pros seem to me to be very little compared to the cons of the ... and
the (m-n) point Chris was trying to explain doesn't seem that relevant
to me.
I always thought since python is trying so hard to be as intuitive as
it can get it would be the other way (you have 1 apple, you start
counting from 1 ...
[snip]
But you might not have any apples, so you should start from 0! :)
 
C

Carl Banks

You have repeated several cs based points already stated. But apart
from a programming standpoint - could you give a few examples, where
"on paper" (as to avoid stepping into "programmer's territory") zero
indexing could be more intuitive ?

That's beside the point. Python's job is to be usable as a
programming language. It made a decision to use zero-based indexing
so as to simplify programming usage. Therefore, that's what you have
to use for matrix indices, whether it is intuitive for you or not.

I have no real opinion whether zero- or one-based indexing works best
on paper for engineering calculations, except that it's a trivial
consideration.
(of course, taking into account your previous based calculations,
which are based on 1 indexing - I imagine you still use matrices with
a11 as a first element)

I don't know what you're referring to by my previous based
calculations, and the sentences doesn't make sense, so I can't answer
this.

FTR: I use zero-based matrix indices when I'm using a language with
zero-based indexing, and one-based indices when using a language with
one-based indexing. Simple as that. You should do the same.


Carl Banks
 
M

MRAB

andrew said:
MRAB said:
Steven said:
On Wed, 01 Apr 2009 04:58:48 +0200, Lada Kugis wrote:

Why do we try to create languages that are intuitive to humans, then ?
Because of the foolish hope that sufficiently easy syntax will make
excellent programmers out of average people.

Programming is not intuitive to humans. *Counting* isn't intuitive to
humans -- children need to learn how to count.
[snip]
Research suggests that your wrong. For example, even baby chicks can
count:

http://news.bbc.co.uk/1/hi/sci/tech/7975260.stm

i saw that earlier today. it's really pushing the definition of "count",
at least as described there.

there have been similar experiments where they address whether the animal
is actually looking at "how big" the total "pile" is rather than counting
(do they know the difference between two small things and one big thing,
for example). that experiment doesn't seem to address this.
Just occurred to me. Chicks and eggs, on 1 April, with Easter
approaching. Hmm...
 
M

Mensanator

You have repeated several cs based points already stated. But apart
from a programming standpoint - could you give a few examples, where
"on paper" (as to avoid stepping into "programmer's territory") zero
indexing could be more intuitive ?

Here's an easy example: Standard Positional Number Systems.

765 in octal is

7 * 8**2 +
6 * 8**1 +
5 * 8**0

123 in decimal is

1 * 10**2 +
2 * 10**1 +
3 * 10**0

666 in hexadecimal is

6 * 16**2 +
6 * 16**1 +
6 * 16**0

0-based indexing is kinda important.
 
L

Lou Pecora

Lada Kugis said:
You have repeated several cs based points already stated. But apart
from a programming standpoint - could you give a few examples, where
"on paper" (as to avoid stepping into "programmer's territory") zero
indexing could be more intuitive ?

This has become a moving target. I thought your original complaint was
about Python (the programming language) vs. Fortran (the programming
language) and C (the programming language used in an odd way).
 
A

Arnaud Delobelle

Lada Kugis said:
I'm coming from fortran and c background so I'm certainly biased by
them. But if you could explain one thing to me:

in fortran for example:
for i=1,n
goes from 1,2,3,4,...,n

in python for example:
for i in range(1,n)
goes from 1,2,3,4,...,n-1
(that is, it goes from 1 up to, but not including n)

Why is that so ? What were the reasons for that "not including" part ?
It troubles me greatly, and I cannot see it's advantages over the
"standard" "up to and including" n.

Best regards
Lada

Luckily Python allows you to create your own indexing on lists:

def dec(i):
if isinstance(i, slice):
return slice(dec(i.start), dec(i.stop), i.step)
elif i is None or i < 0:
return i
else:
return i - 1

defop = """
def __%sitem__(s,i,*r):
val = list.__%sitem__(s,dec(i),*r)
if isinstance(i, slice): val = List1(val)
return val
def __%sslice__(s,i,j,*r):
return List1(list.__%sslice__(s,dec(i),dec(j),*r))
"""

class List1(list):
for op in 'del', 'get', 'set':
exec defop % (op, op, op, op)
def index(self, x):
return list.index(self, x) + 1
def insert(self, i, x):
list.insert(self, dec(i), x)
def pop(self, i=None):
return list.pop() if i is None else list.pop(dec(i))
for op in 'add', 'mul', 'radd', 'rmul':
exec "def __%s__(*r): return List1(list.__%s__(*r))" % (op, op)

l1 = List1(range(10))
l2 = List1("Python rules")


I'll let you play with l1 and l2.
 
C

Carl Banks

Luckily Python allows you to create your own indexing on lists:

def dec(i):
    if isinstance(i, slice):
        return slice(dec(i.start), dec(i.stop), i.step)
    elif i is None or i < 0:
        return i
    else:
        return i - 1

defop = """
def __%sitem__(s,i,*r):
    val = list.__%sitem__(s,dec(i),*r)
    if isinstance(i, slice): val = List1(val)
    return val
def __%sslice__(s,i,j,*r):
    return List1(list.__%sslice__(s,dec(i),dec(j),*r))
"""

class List1(list):
    for op in 'del', 'get', 'set':
        exec defop % (op, op, op, op)
    def index(self, x):
        return list.index(self, x) + 1
    def insert(self, i, x):
        list.insert(self, dec(i), x)
    def pop(self, i=None):
        return list.pop() if i is None else list.pop(dec(i))
    for op in 'add', 'mul', 'radd', 'rmul':
        exec "def __%s__(*r): return List1(list.__%s__(*r))" % (op, op)

l1 = List1(range(10))
l2 = List1("Python rules")

I'll let you play with l1 and l2.

If I were your boss and you ever pulled something like this, your ass
would be so fired.

This is unforgiveable, not only changing the indexing semantics of
Python (because a user would have NO CLUE that something underlying
has been changed, and thus it should never be done), but also for the
needless abuse of exec.


Carl Banks
 
J

John O'Hagan

Dragging this back to the original topic, you clearly find starting list
indices from zero unintuitive. To me, with a mathematical background,
it's not just intuitive, it's correct. All sorts of useful properties
fall out from that, not the least of which is the fact that
"a[0:len(a)]" slices the whole of a list.

But some non-useful properties fall out of that too.

Want the fifth item? a[5] gives you the *sixth* item, which is weird, so
you have to use a[5-1] to get the fifth item.

There is a major clash between the names of ordinals in human languages
and zero-based counting. In human languages, the Nth-ordinal item comes
in position N. You can keep that useful convention with zero-based
counting by inventing the ugly word "zeroth", but that just leads to
bizarro-talk like "the zeroeth item comes first, the first item comes
second, and so on".

a[0:len(a)] is legal, a[0] is legal, but surprisingly a[len(a)] is an
error.

Despite coming from a Pascal background, I've come to appreciate and
prefer zero-based indexing for programming. But I'm not blind to the
disadvantages. I'll often work out an algorithm using pencil and paper
and counting from one, and then subtract one to get zero-based indexes.

[...]

Despite being thoroughly acclimatised to zero-based indexing and having no
wish to change it, I'm starting to see the OP's point.

Many of the arguments presented in this thread in favour of zero-based
indexing have rather been arguments for half-open intervals, which I don't
think are in dispute. We all want these to be true:

foo[:n] is the first n items of the sequence foo
foo[:n] + foo[n:] == foo
len(foo[n:m]) == m-n
(foo[n:n]) is an empty sequence
etc.

and they are true with 0-based indexing if we exclude the last number, or
equally with 1-based indexing if we exclude the first.

In a way, Python already has 1-based indexing, in terms of absolute index
values when counting backwards: the last element of a sequence is indexed -1,
the second-last -2, etc., so that the first element is foo[-len(foo)].

1-based indexing mirrors this so that foo[len(foo)] is not a surprising error
as Steven mentions above, but the last element of foo.

Also the other weirdness Steven mentioned goes away: the nth element of foo
becomes foo[n], and the OP's issue with an extant element having an
ordinality of 0 ("zeroeth") also goes away, i.e. ordinality and cardinality
are lined up.

Beyond being part of a conventionally-ordered set of keys, what can an
ordinality of zero actually mean? (That's a sincere question.)

But as long as we need to both count items and measure intervals, we have to
deal with these +/-1 adjustments in any case.

As an aside, a similar issue arises in music theory, in which intervals are
traditionally expressed relative to scale degrees starting from one (counting
the notes), or in more modern language, in semitones starting from zero
(measuring the interval). This gives rise to similar (minor and short-lived)
confusions.

+/-1 :)

Regards,

John
 
L

Lie

There is a major clash between the names of ordinals in human languages
and zero-based counting. In human languages, the Nth-ordinal item comes
in position N. You can keep that useful convention with zero-based
counting by inventing the ugly word "zeroth", but that just leads to
bizarro-talk like "the zeroeth item comes first, the first item comes
second, and so on".

No, there won't be any bizarro-talk. There is no argument: the zeroeth
item comes zeroeth, the first item comes first, and so on. The index
for the very zeroeth thing in a list is 0, so to get the zeroeth item
you use s[0]. While to get the first item you use s[1]. It's very
intuitive, isn't it?
 
A

Aaron Brady

There is a major clash between the names of ordinals in human languages
and zero-based counting. In human languages, the Nth-ordinal item comes
in position N. You can keep that useful convention with zero-based
counting by inventing the ugly word "zeroth", but that just leads to
bizarro-talk like "the zeroeth item comes first, the first item comes
second, and so on".

No, there won't be any bizarro-talk. There is no argument: the zeroeth
item comes zeroeth, the first item comes first, and so on. The index
for the very zeroeth thing in a list is 0, so to get the zeroeth item
you use s[0]. While to get the first item you use s[1]. It's very
intuitive, isn't it?

Robot 1: I won zeroeth place at the contest, honey!
Robot 2: Congratulations! I knew you could do it.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top