xslice idea | a generator slice

R

Russel Walker

Just some dribble, nothing major.

I like using slices but I also noticed that a slice expression returns a new sequence.

I sometimes find myself using them in a for loop like this:


seq = range(10)
for even in seq[::2]:
print even


(That's just for an example) But wouldn't it be a bit of a waste if the slice expression returns a whole new list just when all you want to do in this case is iterate over it once?

I suppose you could get around that will a little more code like:


seq = range(10)
for x in xrange(0, len(seq), 2):
print seq[x]


But it would be nice there was a way to iterate over a 'slice' of sorts, that would act as a generator.

So I tried my handle at a little class called xslice (the x from xrange to indicate its a generator (although I'm not sure if that's technically correct)).

With it, instead of the above example you can do:


seq = range(10)
for even in xslice(seq, 0, len(seq), 2):
print even


It would be more or less like using xrange. I know the syntax is not that much of an improvement over just using exrange and retrieving items by index, but it's the concept I'm looking at.

Do you think this or something like be a builtin in the future?
 
R

Russel Walker

....oh and here is the class I made for it.

class xslice(object):
'''
xslice(seq, start, stop, step) -> generator slice
'''

def __init__(self, seq, *stop):
if len(stop) > 3:
raise TypeError("xslice takes at most 4 arguments")
elif len(stop) < 0:
raise TypeError("xslice requires atleast 2 arguments")
else:
start, stop, step = (((0,) + stop[:2])[-2:] + # start, stop
(stop[2:] + (1,))[:1]) # step
stop = min(stop, len(seq))
self._ind = iter(xrange(start, stop, step))
self._seq = seq

def __iter__(self):
return self

def next(self):
return self._seq[self._ind.next()]



Although now that I think about it, it probably should've just been a simple generator function.
 
I

Ian Kelly

Just some dribble, nothing major.

I like using slices but I also noticed that a slice expression returns a new sequence.

I sometimes find myself using them in a for loop like this:


seq = range(10)
for even in seq[::2]:
print even


(That's just for an example) But wouldn't it be a bit of a waste if the slice expression returns a whole new list just when all you want to do in this case is iterate over it once?

I suppose you could get around that will a little more code like:


seq = range(10)
for x in xrange(0, len(seq), 2):
print seq[x]


But it would be nice there was a way to iterate over a 'slice' of sorts, that would act as a generator.

That would be the itertools.islice function.
 
R

Russel Walker

def __init__(self, seq, *stop):
Wouldn't it be better if it has the same signature(s) as itertools.islice?

That's actually what I was going for, except I was modeling it after range,but that was the only way I knew to implement it.

How would len(stop) be negative?


Yes, that should've been len(stop) < 1.

Or you can use itertools.imap:



def xslice(sequence, start_or_stop, *args):

indices = xrange(*slice(start_or_stop, *args).indices(len(sequence)))

return imap(sequence.__getitem__, indices)





Oscar


I like the way you did that with imap, although I still like my parameter implementation.

To confess, this is the second time I've made the mistake of trying to implement generator like functionality of a builtin when there already is on initertools. Need to start studying that module abit more I think. I'm looking at the docs now and I see there are actually a couple of isomethings().
 
O

Oscar Benjamin

To confess, this is the second time I've made the mistake of trying to implement generator like functionality of a builtin when there already is on in itertools. Need to start studying that module abit more I think. I'm looking at the docs now and I see there are actually a couple of isomethings()..

Your xslice (or mine) would still be better than islice when the step
size is large; islice has to iterate over all the skipped elements
which could be wasteful if the input is indexable. Also islice doesn't
support negative values for start, stop or step which xslice does.
 
I

Ian Kelly

Your xslice (or mine) would still be better than islice when the step
size is large; islice has to iterate over all the skipped elements
which could be wasteful if the input is indexable. Also islice doesn't
support negative values for start, stop or step which xslice does.

Ah, that's an interesting point. Of course the corollary to that is
that xslice requires a sequence, not just an iterable.
 
F

Fábio Santos

implement generator like functionality of a builtin when there already is
on in itertools. Need to start studying that module abit more I think. I'm
looking at the docs now and I see there are actually a couple of
isomethings().
Your xslice (or mine) would still be better than islice when the step
size is large; islice has to iterate over all the skipped elements
which could be wasteful if the input is indexable. Also islice doesn't
support negative values for start, stop or step which xslice does.

Isn't all of itertools implemented in C? If we are not using a python-level
and not-so-fast __getitem__ I would wager the C version is a lot faster.

And if the input is indexable could I assume that it is not too large to
have around in memory and thus any speed increase in looping over it would
be tiny?
 
I

Ian Kelly

Isn't all of itertools implemented in C? If we are not using a python-level
and not-so-fast __getitem__ I would wager the C version is a lot faster.

And if the input is indexable could I assume that it is not too large to
have around in memory and thus any speed increase in looping over it would
be tiny?

Oscar's version which is an imap of an xrange is also effectively
implemented in C. Only the setup is in Python.
 

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

Forum statistics

Threads
473,757
Messages
2,569,543
Members
45,026
Latest member
camilin05

Latest Threads

Top