[Tutor] making len() and __len__ return a non-int
Albert-Jan Roskam
fomcl at yahoo.com
Sun Sep 2 21:06:38 CEST 2012
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 at python.org
>To unsubscribe or change subscription options:
>http://mail.python.org/mailman/listinfo/tutor
>
>
>
________________________________
From: Peter Otten <__peter__ at web.de>
To: tutor at python.org
Sent: Sunday, September 2, 2012 2:36 PM
Subject: Re: [Tutor] making len() and __len__ return a non-int
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20120902/623471c7/attachment.html>
More information about the Tutor
mailing list