Why len(x) is not just x.__len__() in disguise
Implicit operations such as len use a type-level special method protocol, which differs from ordinary attribute lookup on an instance.
An operation can be a protocol request
Many Python operations have a compact syntax: len(x), iteration with for, or indexing with brackets. The language maps these forms to protocols that types implement. For length, an object’s type provides the relevant special method; the protocol is not simply ordinary lookup of an attribute named __len__ on the instance. The data model describes each object as having a type that determines supported operations. [1]
This separation gives built-in syntax a stable meaning even when an individual object has attributes added to it. Ordinary attribute access and implicit special method dispatch answer different questions: the first asks what this instance exposes under a name, while the second asks how its type participates in a language operation.
The class supplies the protocol behavior
In the example, the class defines __len__ to return 3, and an instance is created. Assigning a lambda to x.__len__ then adds an instance attribute that returns 9 when called explicitly. The built-in len(x) still produces 3, because the implicit operation uses the special method associated with the type. The direct call x.__len__() performs normal instance attribute lookup and produces 9. [1]
Thus the exact output is 3 followed by 9. There is no inconsistency: one expression asks the length protocol, and the other calls the attribute found on that particular instance. This distinction is useful when an object seems to ignore a dynamically attached method during an operator or built-in call.
class Sized:
def __len__(self):
return 3
x = Sized()
x.__len__ = lambda: 9
print(len(x)) # 3
print(x.__len__()) # 9
Special methods are not ordinary hooks everywhere
A special method is a type-level protocol hook for a particular operation, not a general promise that every same-named instance attribute will intercept that operation. Defining the method on the class makes instances participate in the protocol. Setting the name on one instance can still affect explicit attribute access, as the example demonstrates, without changing what len dispatches.
This design has limits and consequences. A per-instance override is not a reliable way to customize language operations such as length; use a class whose type defines the behavior. Conversely, changing a class-level special method can affect protocol behavior for its instances, which is a broader change than attaching a temporary attribute to one object. The mechanism keeps implicit operations tied to type behavior rather than arbitrary per-instance state.
Choose the question before choosing the syntax
If the goal is to ask for the number of elements according to an object’s length protocol, use len(x). If the goal is to inspect or invoke the instance attribute currently named __len__, use the explicit method access. They can produce different results when an instance attribute shadows the normal class attribute, because the two forms follow different lookup paths.
The same mental distinction helps with other operator protocols: special syntax expresses an operation, and the type defines how instances support it. Treating every operator as a spelling shortcut for an instance method call leads to surprising cases. Treating it as a protocol request makes the class boundary and the observed output understandable. [1]