[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