Reputation: 18084
Is there any case where len(someObj)
does not call someObj's __len__
function?
I recently replaced the former with the latter in a (sucessful) effort to speed up some code. I want to make sure there's not some edge case somewhere where len(someObj)
is not the same as someObj.__len__()
.
Upvotes: 15
Views: 2272
Reputation: 33127
There are cases where len(someObj)
is not the same as someObj.__len__()
since len()
validates __len__()
's return value. Here are the possible errors in Python 3.6.9:
Too low, i.e. less than 0
ValueError: __len__() should return >= 0
Too high, i.e. greater than sys.maxsize
(CPython-specific, per the docs)
OverflowError: cannot fit 'int' into an index-sized integer
An invalid type, e.g float
TypeError: 'float' object cannot be interpreted as an integer
Missing, e.g. len(object)
TypeError: object of type 'type' has no len()
I mention this because object.__len__()
raises a different exception, AttributeError
.
It's also worth noting that range(sys.maxsize+1)
is valid, but its __len__()
raises an exception:
OverflowError: Python int too large to convert to C ssize_t
Upvotes: 3
Reputation: 20550
If __len__
returns a length over sys.maxsize
, len()
will raise an exception. This isn't true of calling __len__
directly. (In fact you could return any object from __len__
which won't be caught unless it goes through len()
.)
Upvotes: 18
Reputation: 27107
I think the answer is that it will always work -- according to the Python docs:
__len__(self):
Called to implement the built-in function len(). Should return the length of the object, an integer >= 0. Also, an object that doesn't define a __nonzero__()
method and whose __len__()
method returns zero is considered to be false in a Boolean context.
Upvotes: 3
Reputation: 116998
What kind of speedup did you see? I cannot imagine it was noticeable was it?
From http://mail.python.org/pipermail/python-list/2002-May/147079.html
in certain situations there is no difference, but using len() is preferred for a couple reasons.
first, it's not recommended to go calling the
__methods__
yourself, they are meant to be used by other parts of python.
len()
will work on any type of sequence object (lists
,tuples
, and all).__len__
will only work on class instances with a__len__
method.
len()
will return a more appropriate exception on objects without length.
Upvotes: 12
Reputation: 28235
According to Mark Pilgrim, it looks like no. len(someObj)
is the same as someObj.__len__()
;
Cheers!
Upvotes: -4