Is arr.__len__ the preferred way to get the length of an array in Python?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
No — len(arr) is the preferred way to get the length of an array, list, or any sequence in Python. Calling arr.__len__() directly works but violates Python conventions. The built-in len() function is the idiomatic approach because it provides a consistent interface, includes type checking, and is recognized by every Python developer. The __len__ method exists so that custom objects can support len(), not so that you call it directly.
len() vs len()
Both return the same value, but len() is the standard. Python's design philosophy (documented in PEP 8) says to use built-in functions rather than calling dunder methods directly.
Why len() Is Preferred
len() enforces that the result is a non-negative integer. Calling __len__() directly bypasses these safety checks. This matters when working with third-party objects that may have buggy implementations.
How len() Works Internally
In CPython, len() is implemented in C and calls __len__ through the type's slot mechanism, which is faster than a Python-level method call.
Implementing len in Custom Classes
Implementing __len__ on your class enables len(obj) and also makes the object truthy/falsy based on its length. An empty container is falsy, a non-empty one is truthy.
len and Boolean Context
When Python evaluates if obj:, it calls bool(obj). If the class defines __len__ but not __bool__, Python uses __len__() != 0 as the boolean value.
Performance Comparison
len() is faster because CPython optimizes it as a C function that accesses the internal length field directly through the type's slot, avoiding the overhead of Python-level attribute lookup and method dispatch.
Other Dunder Methods You Should Not Call Directly
The pattern is consistent across Python — dunder methods are implementation hooks, not part of the public API. Use the corresponding built-in function or operator.
Common Pitfalls
- Calling len() directly in production code: It bypasses validation, is harder to read, and is slower. Always use
len(). - Forgetting len returns int: If your custom
__len__returns a float or string,len()raisesTypeError. Always return an integer. - Confusing len() with sys.getsizeof():
len([1, 2, 3])returns 3 (number of elements).sys.getsizeof([1, 2, 3])returns the memory footprint in bytes. They measure different things. - Assuming len() is O(1) for all types:
len()is O(1) for lists, tuples, dicts, sets, and strings because they store their length internally. Custom classes could implement__len__as O(n) — the cost depends on the implementation. - Not implementing len for container classes: If your class represents a collection, implement
__len__so it works withlen(),bool(), and other Python idioms. Without it,len(obj)raisesTypeError.
Summary
- Always use
len(obj)instead ofobj.__len__()— it is the Pythonic way len()validates the return value (must be a non-negative integer)len()is faster than__len__()due to C-level optimizations in CPython- Implement
__len__in custom classes to supportlen()and boolean evaluation __len__returning 0 makes the object falsy — this powersif not container:patterns- Never call dunder methods directly — use the corresponding built-in function or operator

