<html><body><div style="color:#000; background-color:#fff; font-family:times new roman, new york, times, serif;font-size:12pt"><div style="RIGHT: auto"><FONT size=2 face=Arial>
<DIV style="BORDER-BOTTOM: #ccc 1px solid; BORDER-LEFT: #ccc 1px solid; PADDING-BOTTOM: 0px; LINE-HEIGHT: 0; MARGIN: 5px 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; HEIGHT: 0px; FONT-SIZE: 0px; BORDER-TOP: #ccc 1px solid; BORDER-RIGHT: #ccc 1px solid; PADDING-TOP: 0px" class=hr contentEditable=false readonly="true"></DIV><B><SPAN style="FONT-WEIGHT: bold">From:</SPAN></B> Peter Otten <__peter__@web.de><BR><B><SPAN style="FONT-WEIGHT: bold">To:</SPAN></B> tutor@python.org <BR><B><SPAN style="FONT-WEIGHT: bold">Sent:</SPAN></B> Sunday, September 2, 2012 2:36 PM<BR><B><SPAN style="FONT-WEIGHT: bold">Subject:</SPAN></B> Re: [Tutor] making len() and __len__ return a non-int<BR></FONT></div>
<DIV style="RIGHT: auto">
<BLOCKQUOTE style="BORDER-LEFT: rgb(16,16,255) 2px solid; MARGIN-TOP: 5px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; RIGHT: auto">
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt">
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt" class=ms__id620>Albert-Jan Roskam wrote:<BR><BR>> If I implement __len__ in my own class, does it really have to return an<BR>> int? Is there no way around this (other than modifying the source code of<BR>> python itself ;-) It would be nice if len(Example(row, col)) would return<BR>> a dictionary, or a two-tuple (see code below). The strange thing is that<BR>> calling __len__ directly does work: Example(1, 2).__len__() returns the<BR>> dictionary. I always thought len() was a convenient "shorthand" for<BR>> __len__. I've even been reading about metaclasses (interesting, dark,<BR>> mysterious), thinking the answer might lie there. Note that my question is<BR>> not whether it's a good idea to do this, <BR><BR>Ah, you already know it's a bad idea...<BR><BR>> I just find it interesting to understand how it could be done.<BR><BR>It cannot be done
 without modifying the source.<BR><BR>Here's the implementation of len() in Python 3.3:<BR><BR>static PyObject *<BR>builtin_len(PyObject *self, PyObject *v)<BR>{<BR>    Py_ssize_t res;<BR><BR>    res = PyObject_Size(v);<BR>    if (res < 0 && PyErr_Occurred())<BR>        return NULL;<BR>    return PyLong_FromSsize_t(res);<BR>}<BR></DIV>
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt" class=ms__id620>===> 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<VAR id=yui-ie-cursor></VAR> checking if I could find __builtin__.__len__, but that's not possible, probably because they're all compiled. </DIV>
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt" class=ms__id620> </DIV>
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt" class=ms__id620>Thanks for your help!</DIV>
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt" class=ms__id620> </DIV>
<DIV style="FONT-FAMILY: times new roman, new york, times, serif; FONT-SIZE: 12pt" class=ms__id620>I did not successfully drill down further, but you can see that it may <BR>signal an error or return a Python long (which I think is the same as a <BR>Python int in 3.x) and that the underlying code operates on Py_size_t, so <BR>you'd have to modify that code, too. Py_ssize_t is implementation dependent <BR>-- on my 64-bit Linux valid lengths are in range(0, 2**63):<BR><BR>>>> class A:<BR>...    def __len__(self): return self._len<BR>...    def __init__(self, len):<BR>...            self._len = len<BR>... <BR>>>> len(A(-1))<BR>Traceback (most recent call last):<BR>  File "<stdin>", line 1, in <module><BR>ValueError: __len__() should return >= 0<BR>>>> len(A(2**63))<BR>Traceback (most recent call last):<BR>  File "<stdin>", line 1, in
 <module><BR>OverflowError: cannot fit 'int' into an index-sized integer<BR>>>> len(A(2**63-1))<BR>9223372036854775807<BR><BR><BR>_______________________________________________<BR>Tutor maillist  -  <A href="mailto:Tutor@python.org" ymailto="mailto:Tutor@python.org">Tutor@python.org</A><BR>To unsubscribe or change subscription options:<BR>http://mail.python.org/mailman/listinfo/tutor<BR><BR><BR></DIV></DIV></BLOCKQUOTE></DIV></div></body></html>