0

Is there some philosophical reasoning behind why python uses this syntax:

for x in range(1,11,3):

instead of, for example, the BASIC syntax:

for x = 1 to 10 step 3

If Python is supposed to be more human readable than most languages, in this case particular case it seems to be worse than say Sinclair BASIC.

I was trying to think of how a human might express this. Perhaps "With x taking the values 1 through 10:" Seems like the BASIC way is closer.

2
  • 3
    IMO, it's a good thing that this syntax is so ugly. Most of the time using for x in range is the wrong thing to do in Python. You should instead just iterate the iterable (e.g. list, dict, generator) directly or use enumerate() instead of using range().
    – Lie Ryan
    Nov 8 '19 at 2:12
  • People who are proficient in python very rarely will write for x range(<whatever>):, there are almost always better constructs, usually you just want to iterate over the colleciton itself, like for item in some_list:. Note, range isn't a part of the for-statement syntax, it is merely an object, a sequence, that can be iterated over, like any other iterable. Dec 3 '19 at 23:36
7

Note that range() is not actually part of the python language; it is a function. Having range be a function means you can plug any other function into a "for in" loop, including functions that don't increase monotonically, functions that lazy-execute, and functions that replace range() with something that better satisfies your personal sensibilities.

In other words, python's way affords you tremendous flexibility to do it however you want.

Your example is not exactly a fair one. It describes a scenario that would be very rare in practice. For a dice roll, it is simply

 for x in range(6)
4
  • I guess that's not too bad. But I wouldn't say it's as readable as BASIC.
    – zooby
    Nov 8 '19 at 2:25
  • 2
    Exactly. There is such a thing as too much readability; it gives you things like COBOL. Nov 8 '19 at 7:16
  • 2
    It is not about any "function". It is about any "iterable". Ordinary functions are not iterables - generator functions are. Also, range is a class, not a function. (A similar generator function to be pluggable in for loops would be trivial, but range objects can respond as full Sequences, with random item access and containment checking (in O(1) time) as well.
    – jsbueno
    Nov 8 '19 at 15:13
  • @zooby you aren't understanding, range isn't part of the syntax. The syntax, abstractly, would be something like for <target_name> in <iterable> which is quite readable. Python for-loops are generally used to iterate over containers/iterables/iterators, and not for these sort of ranges. For that particular case, Python has the built-in iterable type range. But again, you rarely see this in any real python code. Dec 3 '19 at 23:38
6

There are multiple different ways to approach this answer (bold emphasis mine):

What is the reason python uses range in for loops?

This is not a for loop. It is a foreach loop. I.e. it is not a loop that loops over a pre-defined set of loop indices, it is an iterator that iterates over the elements of a collection.

In particular, in

for e in [2, 3, 5, 7, 11, 13, 17]:
    print(e)

The result will not be

0
1
2
3
4
5
6

but

2
3
5
7
11
13
17

What is the reason python uses range in for loops?

It doesn't. It uses an arbitrary expression. More precisely, an arbitrary expression that evaluates to an iterator or to something that can be implicitly converted to an iterator (such as an iterable):

class MyIterator:
    def __init__(self):
        self.counter = -1
        self.lost = [4, 8, 15, 16, 23, 42]

    def __next__(self):
        self.counter += 1

        if self.counter == 6:
            raise StopIteration

        return self.lost[self.counter]

class MyIterable:
    def __iter__(self):
        return MyIterator()

my_iterable = MyIterable()

for num in my_iterable:
    print(num)

# 4
# 8
# 15
# 16
# 23
# 42

Is there some philosophical reasoning behind why python uses this syntax

Yes: It is more general and thus makes the language simpler. The BASIC for loop can do one thing and one thing only: loop over a pre-defined set of loop indices. In fact, it is even more limited than that, because there are further restrictions on the loop indices: they need to be monotonically increasing or decreasing with a fixed step size.

If you want the indices to be non-monotonic, you need a new language construct. If you want the indices to have varying step sizes, you need a new language construct. If you want to iterate over the elements of a collection, you need a new language construct.

With Python's foreach loop, you can simply have a function that generates indices in whatever order you want, and loop over those. You can iterate over the elements of any arbitrary collection, and note that "collection" is interpreted very broadly.

Actually, you can iterate over the elements of any arbitrary iterator. An iterator can be something very general, and it doesn't even have to be finite, e.g. "all prime numbers".

As I have shown above, it is very easy to create your own custom iterators and iterables. It is in fact even more easy using generator functions:

def my_generator():
    yield 4
    yield 8
    yield 15
    yield 16
    yield 23
    yield 42

for num in my_generator():
    print(num)

# 4
# 8
# 15
# 16
# 23
# 42

And even more easy with generator expressions.

If Python is supposed to be more human readable than most languages, in this case particular case it seems to be worse than say Sinclair BASIC.

If you are looping over loop indices in Python (or any modern language, really), you are doing it wrong.

You should be using higher-level iterators instead, such as reduce (you may also know this one under the name fold or more general Catamorphism), accumulate (you may also know this one under the name scan or prefix-sum), cycle, chain, groupby, or product. Or, you should be using list / set / dictionary comprehensions, generator expressions, or algorithms and data structures supplied by the standard library or third-party libraries.

2
  • Well I'm not so sure about the reason about the fixed steps in a for loop. You can easily do: for x=1 to 10 y=f(x) and have y be your variable. With any function you like for f.
    – zooby
    Nov 9 '19 at 1:28
  • for x in [1,3,5,7,11] is just the same as for y=0 to 4; x=[1,3,5,7,11](y). I think it's debatable whether foreach loops or for loops are more readable. In fact I generally find for loops more readable but maybe that's because I learned BASIC first.
    – zooby
    Nov 9 '19 at 1:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.