K
Kay Schluehr
Steve said:Just because you aren't aware of something doesn't stop it being true.
The argument must be iterable, and there's a specific protocol for that.
Ah, so you *were* aware of it.
I already responded to it two days ago in the reply to Terry. No need
to rehash that.
The advantage being ... ? Perhaps you have just discovered a really
interesting hammer, and are seeing this problem as a nail?
I also responded to traits as nice-to-have but not essential. And
please don't aggressively consider me as childish as you might be
yourself.
Adding a __traits__ attribute should enable the user adding methods to
builtins in a safe manner. This has the advantage that one can apply
methods to string or integer literals or even replace methods without
touching the C sources. A very typical use case is integer
representation. In 95% of all my business applications I don't have
much use for decimal integer representation but want a hex rep in
different variants:
02 BC
I know I can write wrapper classes, because I do this all the time, but
that's not the point: Python is essentially not about boiler-plate. And
no, I also don't want to fight for each method and keyword with Guido.
That would indeed be a naïve implementation.
And that's the real implementation:
static PyObject *
builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds)
{
PyObject *newlist, *v, *seq, *compare=NULL, *keyfunc=NULL, *newargs;
PyObject *callable;
static char *kwlist[] = {"iterable", "cmp", "key", "reverse", 0};
long reverse;
if (args != NULL) {
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOi:sorted",
kwlist, &seq, &compare, &keyfunc, &reverse))
return NULL;
}
newlist = PySequence_List(seq);
if (newlist == NULL)
return NULL;
callable = PyObject_GetAttrString(newlist, "sort");
if (callable == NULL) {
Py_DECREF(newlist);
return NULL;
}
newargs = PyTuple_GetSlice(args, 1, 4);
if (newargs == NULL) {
Py_DECREF(newlist);
Py_DECREF(callable);
return NULL;
}
v = PyObject_Call(callable, newargs, kwds);
Py_DECREF(newargs);
Py_DECREF(callable);
if (v == NULL) {
Py_DECREF(newlist);
return NULL;
}
Py_DECREF(v);
return newlist;
}
The crucial steps are the conversion from args to seq, the conversion
from seq to newlist and finally calling PyObject_Call(callable, ...)
where callable stores the sort method of newlist. By the way I don't
see much use in implementing this trivial wrapper function in C except
for the joy of refcounting
And now we take a look on how the PyPythonistas implemented sorted():
def sorted(lst, cmp=None, key=None, reverse=None):
"sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted
list"
sorted_lst = list(lst)
sorted_lst.sort(cmp, key, reverse)
return sorted_lst
Surprise, surprise!
The implementation is, of
course, an implementation detail ;-) In this case it requires that
sort() then provides all the magic - the need for magic doesn't go away!
Has anyone denied the necessaty of sort()?
Kay