<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>I'm aware that syntax for ranges and slices has been discussed a good amount over the years, but I wanted to float an idea out there to see if it hasn't been considered before. It's not really original. Rather, it's a combination of a couple parts of Python, and I find it fascinatingly-consistent with the rest of the language. This will look similar to PEP 204, but there are some important differences and clarifications.</div><div><br></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><font face="monospace, monospace">(start:stop:step)</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>Meet a range/slice object. Parentheses are required. (Its syntax in this regard follows exactly the same rules as a generator expression.) I say both range and slice because it can be used in either role. On the one hand, it is iterable and functions exactly like range(start, stop, step) in those contexts. On the other, it can also be passed into list indexing exactly like slice(start, stop, step). This is a proposal that range and slice are really the same thing, just in different contexts.</div><div><br></div><div>Why is it useful? I at least find its syntax to be simple, intuitive, and concise -- more so than the range(...) or slice(...) alternatives. It's quite obvious for an experienced Python user and just as simple to pick up as slice notation for a beginner (since it <i>is</i> slice notation).</div><div><br></div><div>It condenses and clears up sometimes-cumbersome range expressions. A couple examples:</div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">sum(1:6) # instead of sum(range(1, 6))</font></div></div></div></div></div></div></div><div><font face="monospace, monospace"><br></font></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace">list(1:6)</font></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><div><font face="monospace, monospace">for i in (1:6):</font></div></div></div></div></div></div></div></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><div><font face="monospace, monospace">print(i**2)</font></div></div></div></div></div></div></div></div></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">(i**2 for i in (1:6))</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>It also makes forming reusable slices clearer and easier:</div><div><br></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">my_slice = (:6:2) # instead of slice(None, 6, 2)</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">my_list[my_slice]</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>It has a couple of siblings that should be obvious (think list or set comprehension):</div><div><br></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">[start:stop:step] # gives a list</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">{start:stop:step} # gives a set</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>This is similar to passing a range/slice object into the respective constructor:</div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">[1:6] # list(1:6) or [1, 2, 3, 4, 5]</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">{1:6} # set(1:6) or {1, 2, 3, 4, 5}  </font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>Note that the parentheses aren't needed when it is the only argument of a function call or is the only element within brackets or braces. It takes on its respective roles for these bracket and brace cases, just like comprehensions. This also gives rise to the normal slice syntax:</div><div><br class="m_-5279354805460550483m_-495529817140843875gmail-Apple-interchange-newline"></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">my_list[1:6:2] # What is inside the brackets is a slice object.</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">my_list[(1:6:2)] # Equivalent. The parentheses are valid but unnecessary.</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>So here's the part that requires a little more thought. Any of the values may be omitted and in the slice context the behavior has no changes from what it already does: start and stop default to the beginning or end of the list depending on direction and the step defaults to 1. In the range context, we simply repeat these semantics, but noting that there is no longer a beginning or end of a list.</div><div><br></div><div>Step defaults to 1 (just like range or slice).</div><div>Start defaults to 0 when counting up and -1 when counting down (just like slice).</div><div>If stop is omitted, the object will act like an itertools.count object, counting indefinitely.</div><div><br></div><div>I have found infinite iteration to be a natural and oft-desired extension to a range object, but I can understand that some may want it to remain separate and pure within itertools. I also admit that the ability to form an infinite list with only three characters can be a scary thought (though we are all adults here, right? ;). Normally you have to take a couple extra keystrokes:</div><div><br></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">from itertools import count</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">list(count())</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace"># rather than just [:]</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>If that is the case, then raising an error when iter() is called on a range/slice object with no stop value could be another acceptable course of action. The syntax will still be left valid.</div><div><br></div><div>And that's mainly it. Slice is iterable or range is "indexable" and the syntax can be used anywhere successive values are desired. If you want to know what it does or how to use it in some case, just think, "what would a slice object do?" or "what would a range object do?" or "how would I write a generator expression/list comprehension here?".</div><div><br></div><div>Here are a few more examples:</div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">for i in (:5): # 5 elements 0 to 4, i.e. range(5)</font></div></div></div></div></div></div></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">print(i**2)</font></div></div></div></div></div></div></div></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace"> for i in (1:): # counts up from one for as long as you want, i.e. count(1)</font></div></div></div></div></div></div></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><span style="font-family:monospace,monospace">print(i**2)</span></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">if i == 5: break</font></div></div></div></div></div></div></div><div><font face="monospace, monospace"><br></font></div></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><font face="monospace, monospace">it = iter(:) # a convenient usage for an infinite counter</font></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">next(it)</font></div></div></div></div></div></div></div></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace"><br></font></div><div><div><div><div><div><div><div><font face="monospace, monospace">' '.join(map(str, (:5:2))) # gives '0 2 4'</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">[(:5), (5:10)] # list of range/slice objects</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">[[:5], [5:10]] # list of lists</font></div></div></div></div></div></div></div><div><div><div><div><div><div><font face="monospace, monospace">[*(:5), *(5:10)] # uses unpacking to get flat list

</font></div></div></div></div></div></div><div><div><div><div><div><div><font face="monospace, monospace">[*[:5], *[5:10]] # same unpacking to get flat list</font></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>Otherwise you'd have to do:</div><div><br></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">[list(range(5)), list(range(5, 10))] # list of lists</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">[*range(5), *range(5, 10)] # flat list</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>Tuples:</div><div><br></div></div></div></div></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div><div><div><div><div><font face="monospace, monospace">tuple(1:6:2) # (1, 3, 5)</font></div></div></div></div></div></div></div><div><div><div><div><div><div><div><font face="monospace, monospace">*(1:6:2), # same</font></div></div></div></div></div></div></div></blockquote><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><br></div><div>I don't actually have experience developing the interpreter and underlying workings of Python, so I don't know how much of a change this requires. I thought it might be possible since the constructs already exist in the language. They just haven't been unified yet. I also realize that there are a few other use-cases that need to be ironed out. The syntax might also be too minimal in some cases to be obvious. One of the trickiest things may be what it will be called, since the current language has the two different terms.</div><div><br></div><div>In the end it's just another range/slice idea, and the idea has probably already been proposed sometime in the past few decades, but what thoughts are there?</div><div><br></div><div>- Nicholas</div></div></div></div></div></div></div></div>