[Python-ideas] Allow popping of slices

Ben Rudiak-Gould benrudiak at gmail.com
Tue Jun 5 03:18:16 EDT 2018

On Mon, Jun 4, 2018 at 5:11 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> class MyList(list):
>     def pop(self, pos):
>         if isinstance(pos, slice):
>             temp = self[pos]
>             del self[pos]
>             return temp
>         return super().pop(pos)
> Is that what you have in mind?

Yes. (I used almost exactly that to test my examples.)

>>     def cut_deck(deck, pos):
>>         deck.extend(deck.pop(slice(0, pos)))
> I'm not sure that's an advantage over:
>     deck[:] = deck[pos:] + deck[:pos]
> but I suppose one might be faster or slower than the other. But I think
> the version with slices is much more clear.

That's fair. I didn't spend as long creating examples as I probably should've.

> It might help your argument if you show equivalent (but working) code
> that doesn't rely on popping a slice.

When I have a collection of items and I want to consume them, process
them, and produce a new collection of items, I often find myself
writing something along the lines of

    items2 = []
    for item in items:
    items = items2
    del items2

The last two statements aren't strictly necessary, but omitting them
is a bug factory in my experience; it's too easy to use the wrong
variable in subsequent code.

When the loop is simple enough I can write

    items = [... for item in items]

and when it's complicated enough it probably makes sense to split it
into a separate function. But I've many times wished that I could

    for item in items.pop_all():

This proposal uses pop(slice(None)) instead, because it's a natural
extension of the existing meaning of that method.

My bfs function was a breadth-first search. The outer loop runs once
for each depth, and the inner loop once for each item at the current
depth (the frontier). The code in the Wikipedia article uses a FIFO
queue instead and has just one loop (but doesn't explicitly track the

> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
> Do you have a link for the Perl version?


It's slightly more versatile: it essentially does

    return old

The special case LIST = [] is what I'm suggesting for the pop method.

>> I think it's useful not just because it's more
>> concise, but because it's linear/reversible: it moves data rather than
>> duplicating and then destroying it, which makes it less prone to bugs.
> I don't see how that is possible. You still have to move the data out of
> the sequence into a new sequence before deleting it from the original.

Under the hood it copies data because that's how von Neumann machines
work, but from the Python programmer's perspective it moves it.

(Similarly, std::swap(x, y) in C++ probably does { t = x; x = y; y =
t; } internally, but it looks like a swap from the programmer's

>>  3. Promote del statements to expressions that return the same values
>> as the underlying __delitem__, __delattr__, etc., and make those
>> methods of built-in types return the thing that was deleted. (Or
>> introduce __popitem__, __popattr__, etc. which return a value.)
> I don't get how this allows us to pass slices to pop.

It doesn't; it basically makes del the new pop. It's almost pop
already, except that it doesn't return the deleted value.

I wasn't seriously proposing this, although I do like the idea. I
don't think it reaches the usefulness threshold for new syntax. Also,
del foo[:] would be slower if it had to move the deleted items into a
new list whether or not the caller had any interest in them. That's
why I suggested that del expressions call __popXXX__ instead, while
del statements continue to call __delXXX__; but now it's getting
complicated. Oh well.

-- Ben

More information about the Python-ideas mailing list