[Python-Dev] syntactic shortcut - unpack to variably sized list

Nick Coghlan ncoghlan at iinet.net.au
Sun Nov 14 10:45:42 CET 2004


David Wilson wrote:
> I dislike the use of 'popslice' as it implies somewhere along the lines 
> the use of the slice type, which isn't happening.

If I was writing it, using a slice object as an argument to 
PySequence_GetItem is *exactly* the method I would be using to implement it:

   indices = PySlice_New(start, end, step);
   x = PySequence_GetItem(L, indices);
   PySequence_DelItem(L, indices);
   return x;

Add reference counting, error checking and actually hook this up to the 
list type in the interpreter, and you're basically done.

Heck, it could be argued that list.pop should just accept slices for the 
argument:

   a, b = L.pop(slice(2)) # Pop the first two items
   x, y, z = L.pop(slice(1:6:2)) # Pop items 1, 3 & 5

No new method required in that case - if you provide an index to 
list.pop, it will return a single item, if you provide a slice object, 
it will return a list. (Similar to the way list.__getitem__ currently works)

 > Also, what if at some
 > future date it is decided that all magical syntax should be exposed
 > using friendly method names too? Then you might have a list.slice which
 > work in a much different way.[1]

List slicing is already exposed in Python in a few ways:

   L[:2]
   L.__getitem__(slice(2))
   operator.itemgetter(slice(2))(L)

Adding yet another way to spell it doesn't seem too likely. Given that 
lists *had* a __getslice__ method, and it has since been deprecated in 
favour of slice() objects, I'd be especially surprised to see list.slice 
(or equivalent) making a comeback.

I will note that I only looked into the history of slicing this evening 
(when checking the C API for the sample implementation above). Having 
done so, the trend seems to have been away from having special methods 
for handling slices (__getslice__, __setslice__, __delslice__), and 
towards methods which can handle either a numeric index or a slice 
object (__getitem__, __setitem__, __delitem__).

So maybe "list.pop(slice(2))" is the way to go (a non-optimised version 
could be written fairly easily using the existing internal list 
functions to retrieve and then delete the data. The main trick would be 
to leave the standard path through listpop alone to avoid any 
performance hit to the current users of list.pop() and list.pop(x)).

> Second of all, you cannot have a non-default argument follow a default 
> argument, so your proposed syntax would not work without breaking 
> standard semantics and writing special code to act differently depending 
> on the argument list length, and also take into account if keyword args 
> are used, etc, etc.

The signature I proposed is identical to the existing signatures for the 
builtins range(), xrange() and slice().

It's true that normal Python functions and methods can't have a 
signature like that (it's a syntax error). C extensions (including the 
CPython interpreter) can do whatever they want, though. In this case, I 
think being consistent with slice() is more important than being 
consistent with normal function signatures.

However, the suggestion above (allowing slice objects as arguments to 
list.pop) takes advantage of the existing slice() builtin, so none of 
that non-standard argument handling would need to be duplicated.

> For an extra method, +1, but with a different name (I was thinking 
> 'popitems', but dict.popitem returns a (k, v)).

What do you think of allowing slice objects to be used with list.pop()?

> Oh one last thought. If "*<identifier>" were to be added, then what of 
> "**<identifier>"? I can't think of any use for it, and so the whole 
> scheme might appear confusing to beginners who find they can use ** in 
> function declarations, but not in expressions.

Aye, I don't think it's an accident that "a, b *c = L" has been knocked 
on the head 3 times now. My main gripe with it is that it requires new 
syntax, yet still only supports a small subset of slicing. My idea about 
enhancing list.pop or adding a new method to list to provide the desired 
functionality is aimed at avoiding having the discussion *again* in the 
future (since clearly this is functionality some portion of the user 
community would make use of).

I don't actually need the functionality myself, so I doubt I'll get 
around to providing a sample implementation. But the suggestion is there 
if any of the people that *do* want the feature would like to implement it.

> [1] Exposing magical syntax (eg. indexers) as real methods is the 
> Microsoft way for .NET (or at least, according to a C# book I read). It 
> proves useful in occasions where interoperability with lesser systems is 
> required, for example, a language that does not support custom indexers, 
> or for enabling clients of an object bridge [that does not support 
> cust..] to make full use of your classes.

Python already exposes most things as methods - I found browsing through 
the Language Reference a few months back extremely enlightening in that 
regard (specifically Section 3.3 Special Method Names).

Cheers,
Nick.

-- 
Nick Coghlan               |     Brisbane, Australia
Email: ncoghlan at email.com  | Mobile: +61 409 573 268


More information about the Python-Dev mailing list