Albert-Jan Roskam wrote: > >> If I implement __len__ in my own class, does it really have to return an >> int? Is there no way around this (other than modifying the source code of >> python itself ;-) It would be nice if len(Example(row, col)) would return >> a dictionary, or a two-tuple (see code below). The strange thing is that >> calling __len__ directly does work: Example(1, 2).__len__() returns the >> dictionary. I always thought len() was a convenient "shorthand" for >> __len__. I've even been reading about metaclasses (interesting, dark, >> mysterious), thinking the answer might lie there. Note that my question is >> not whether it's a good idea to do this, > >Ah, you already know it's a bad idea... > >> I just find it interesting to understand how it could be done. > >It cannot be done without modifying the source. > >Here's the implementation of len() in Python 3.3: > >static PyObject * >builtin_len(PyObject *self, PyObject *v) >{ > Py_ssize_t res; > > res = PyObject_Size(v); > if (res < 0 && PyErr_Occurred()) > return NULL; > return PyLong_FromSsize_t(res); >} > >===> aha. So if I do len(Example(1, 2)) the C function "builtin_len" will be >called, whereas if I formulate it like Example(1, 2).__len__(), only the >__len__ special method of my own bogus class will be called. Interesting. I >was already checking if I could find __builtin__.__len__, but that's not >possible, probably because they're all compiled. > >Thanks for your help! > >I did not successfully drill down further, but you can see that it may >signal an error or return a Python long (which I think is the same as a >Python int in 3.x) and that the underlying code operates on Py_size_t, so >you'd have to modify that code, too. Py_ssize_t is implementation dependent >-- on my 64-bit Linux valid lengths are in range(0, 2**63): > >>>> class A: >... def __len__(self): return self._len >... def __init__(self, len): >... self._len = len >... >>>> len(A(-1)) >Traceback (most recent call last): > File "<stdin>", line 1, in <module> >ValueError: __len__() should return >= 0 >>>> len(A(2**63)) >Traceback (most recent call last): > File "<stdin>", line 1, in <module> >OverflowError: cannot fit 'int' into an index-sized integer >>>> len(A(2**63-1)) >9223372036854775807 > > >_______________________________________________ >Tutor maillist - Tutor@python.org >To unsubscribe or change subscription options: >http://mail.python.org/mailman/listinfo/tutor > > >
________________________________ From: Peter Otten <__pete...@web.de> To: tutor@python.org Sent: Sunday, September 2, 2012 2:36 PM Subject: Re: [Tutor] making len() and __len__ return a non-int
_______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor