From an excellent Python Object-Oriented Programming: Build robust and maintainable object-oriented Python applications and libraries, 4th Edition book by Steven F. Lott, and Dusty Phillips
You may wonder why these objects don't have a length property instead of having to call a function on them. Technically, they do. Most objects that len()
will apply to have a method called __len__()
that returns the same value. So len(myobj)
seems to call myobj.__len__()
.
Why should we use the len()
function instead of the __len__()
method? Obviously, __len__()
is a special double-underscore method, suggesting that we shouldn't call it directly. There must be an explanation for this. The Python developers don't make such design decisions lightly.
The main reason is efficiency. When we call the __len__()
method of an object, the object has to look the method up in its namespace, and, if the special __getattribute__()
method (which is called every time an attribute or method on an object is accessed) is defined on that object, it has to be called as well. Furthermore, the __getattribute__()
method may have been written to do something clever, for example, refusing to give us access to special methods such as __len__()
! The len()
function doesn't encounter any of this. It actually calls the __len__()
method on the underlying class, so len(myobj)
maps to MyObj.__len__(myobj)
.