This is the original code.
a = b [0:1] + b [3:4]
This is the simplified code.
a = b [0:1 3:4]
# or
a = b [0:1,3:4]
This is the original code.
a = b [0:1] + b [3:4]
This is the simplified code.
a = b [0:1 3:4]
# or
a = b [0:1,3:4]
That doesn’t look any simpler to me. The first version looks like a mistake (maybe they intended [0:13:4]
?), and the second example conflicts with other uses of indexing, like numpy arrays.
More importantly, this is a breaking change , because slices can hold any arbitrary object.
a[0:"a" "b":2]
concatenates the string into "ab"
, which is indeed valid right now.1,3
currently evaluates to a tuple, which is also valid.Not in this context because the colon takes priority over the comma, 1:2,3:4
as a key already means (slice(1, 2, None), slice(3, 4, None))
.
>>> class Container:
... def __getitem__(self, key):
... return key
...
>>> Container()[1:2,3:4]
(slice(1, 2, None), slice(3, 4, None))
“”“python
a = b[0:1] [3:4]
“””
How does this code look?
This means: Slice from index 3 to 4 from this one-element list.
I wouldn’t characterize the second example as a “conflict” with numpy arrays. The proposal is about list slicing after all. Different classes are free to interpret indexing in different ways. And I think b[0:1, 3:4]
where b
is a list feels intuitive enough to be taught as a concatenation of multiple ranges/slices.
Questions related to slicing in multiple ranges are rather frequently asked on StackOverflow, and the existing solutions are either inefficient (with +
), not super readable (with itertools.chain
), clunky (with for
loops) or requiring a third-party library, so there may be value in adding built-in support for slicing in multiple ranges for lists.
The proposal just says “slicing” and there’s no indication that b
is a list. It’s just a thing getting sliced.
Ah you’re right that the OP didn’t explicitly say it’s for a list. I just presumed it’s for a list because the OP uses the +
operator. I stand by the rest of what I said though.
You can also implement a slicer yourself like this:
class Slicer:
def __init__(self, seq):
self.seq = seq
def __getitem__(self, index):
if isinstance(index, tuple):
return type(self.seq)(
self.seq[i]
for s in index
for i in range(*s.indices(len(self.seq)))
)
return self.seq[index]
so that:
b = list(range(10))
print(Slicer(b)[1:4, 7:9])
outputs:
[1, 2, 3, 7, 8]
Why not just use the slice on the sequence?
return type(self.seq)(
x
for s in index
for x in self.seq[s]
)
Because most sequence types create new copies when sliced and I was trying to avoid creating intermediate sequences.
List slicing is fast though so it may not matter that much.