I know that python has a len()
function that is used to determine the size of a string, but I was wondering why it's not a method of the string object?

- 115,751
- 26
- 228
- 437

- 50,920
- 27
- 77
- 81
-
Related to your update: [Is there any case where `len(someObj)` does not call `someObj`'s `__len__` function?](https://stackoverflow.com/q/496009/4518341) tl;dr Yes, so always use `len()` instead of `__len__()`. – wjandrea Jul 04 '20 at 18:37
7 Answers
Strings do have a length method: __len__()
The protocol in Python is to implement this method on objects which have a length and use the built-in len()
function, which calls it for you, similar to the way you would implement __iter__()
and use the built-in iter()
function (or have the method called behind the scenes for you) on objects which are iterable.
See Emulating container types for more information.
Here's a good read on the subject of protocols in Python: Python and the Principle of Least Astonishment

- 61,926
- 17
- 143
- 150
-
149It astonishes me how moronic the reason for using `len` is. They think that it is easier to force people to implement `.__len__` than to force people to implement `.len()`. Its the same thing, and one looks _much_ cleaner. If the language is going to have an OOP `__len__`, what in the world is the point of making `len(..)` – alternative Nov 07 '11 at 21:13
-
48len, str, etc. can be used with higher-order functions like map, reduce, and filter without the need to define a function or lambda just to call a method. Not everything revolves around OOP, even in Python. – Evicatos Nov 07 '13 at 19:10
-
16Also, by using a protocol, they can provide alternative ways of implementing things. For example, you can create an iterable with `__iter__`, or with only `__getitem__`, and `iter(x)` will work either way. You can create a usable-in-bool-context object with `__bool__` or `__len__`, and `bool(x)` will work either way. And so on. I think Armin explains this reasonably well in the linked post—but even if he didn't, calling Python moronic because of an outside explanation by a guy who's often publicly at odds with the core devs wouldn't exactly be fair… – abarnert Nov 03 '14 at 22:12
-
13@Evicatos: +1 for "Not everything revolves around OOP", but I'd end with "_especially_ in Python", not _even_. Python (unlike Java, Ruby, or Smalltalk) doesn't try to be a "pure OOP" language; it's explicitly designed to be a "multi-paradigm" language. List comprehensions aren't methods on iterables. `zip` is a top-level function, not a `zip_with` method. And so on. Just because everything is an object doesn't mean being an object is the most important thing about each thing. – abarnert Nov 03 '14 at 22:17
-
10That article is so poorly written I feel confused and angry after trying to read it. "In Python 2.x the Tuple type for instance does not expose any non-special methods and yet you can use it to make a string out of it:" The whole thing is an amalgamation of near-indecipherable sentences. – MirroredFate Feb 05 '16 at 18:19
-
“Now if you are asking, why is it x.next() and not next(x): an oversight that was corrected with Python 3” lol if this syntax were really such a natural way of thinking they wouldn’t have made this mistake in the first place… – Andy Jun 11 '23 at 03:00
Jim's answer to this question may help; I copy it here. Quoting Guido van Rossum:
First of all, I chose len(x) over x.len() for HCI reasons (def __len__() came much later). There are two intertwined reasons actually, both HCI:
(a) For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. Compare the easy with which we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness of doing the same thing using a raw OO notation.
(b) When I read code that says len(x) I know that it is asking for the length of something. This tells me two things: the result is an integer, and the argument is some kind of container. To the contrary, when I read x.len(), I have to already know that x is some kind of container implementing an interface or inheriting from a class that has a standard len(). Witness the confusion we occasionally have when a class that is not implementing a mapping has a get() or keys() method, or something that isn’t a file has a write() method.
Saying the same thing in another way, I see ‘len‘ as a built-in operation. I’d hate to lose that. /…/

- 3,358
- 3
- 25
- 36

- 46,145
- 29
- 109
- 133
-
9200+ votes says that the lack of str.len() wastes a ton of people's time coming here and reading why it "should be" intuitive that a string does not have a length function :facepalm: By all means retain the built-in len() function, but why not _also_ support sensible methods on basic things like strings... – GreenAsJade Nov 06 '21 at 03:15
Python is a pragmatic programming language, and the reasons for len()
being a function and not a method of str
, list
, dict
etc. are pragmatic.
The len()
built-in function deals directly with built-in types: the CPython implementation of len()
actually returns the value of the ob_size
field in the PyVarObject
C struct that represents any variable-sized built-in object in memory. This is much faster than calling a method -- no attribute lookup needs to happen. Getting the number of items in a collection is a common operation and must work efficiently for such basic and diverse types as str
, list
, array.array
etc.
However, to promote consistency, when applying len(o)
to a user-defined type, Python calls o.__len__()
as a fallback. __len__
, __abs__
and all the other special methods documented in the Python Data Model make it easy to create objects that behave like the built-ins, enabling the expressive and highly consistent APIs we call "Pythonic".
By implementing special methods your objects can support iteration, overload infix operators, manage contexts in with
blocks etc. You can think of the Data Model as a way of using the Python language itself as a framework where the objects you create can be integrated seamlessly.
A second reason, supported by quotes from Guido van Rossum like this one, is that it is easier to read and write len(s)
than s.len()
.
The notation len(s)
is consistent with unary operators with prefix notation, like abs(n)
. len()
is used way more often than abs()
, and it deserves to be as easy to write.
There may also be a historical reason: in the ABC language which preceded Python (and was very influential in its design), there was a unary operator written as #s
which meant len(s)
.

- 1,981
- 18
- 22
-
4I do not buy the optimality argument. While a method call could indeed be slower, a sufficiently advanced interpreter or compiler –and Python interpreters do much more advanced things than this– could recognize that one is calling the `len` method of a built-in type and revert to returning `ob_size` or whatever it needs, at least the vast majority of the time. – dionyziz Nov 03 '20 at 09:01
-
1@dionyziz: Python's algorithm to look up attributes is very flexible. You have instance attributes, class attributes, data descriptors, not-data descriptors, and multiple-inheritance. All that may play a role in a call like `s.len()`, but does not affect `len(s)`. – Luciano Ramalho Feb 15 '21 at 19:26
There is a len
method:
>>> a = 'a string of some length'
>>> a.__len__()
23
>>> a.__len__
<method-wrapper '__len__' of str object at 0x02005650>

- 33,530
- 16
- 61
- 61
-
6Yes, but it's not meant to be used directly. `len` validates the output of `__len__`. See [Is there any case where `len(someObj)` does not call `someObj`'s `__len__` function?](https://stackoverflow.com/q/496009/4518341) Dunder methods in general are not meant to be called directly. – wjandrea Jul 04 '20 at 18:44
met% python -c 'import this' | grep 'only one'
There should be one-- and preferably only one --obvious way to do it.

- 68,681
- 4
- 36
- 40
-
43The obvious thing when working with an object being, of course, a method. – Peter Cooper May 05 '12 at 23:59
-
5@Peter: I'd pay $20 to anyone with photo evidence that they taped your comment to Guido's back. $50 if it's on his forehead. – bug Jan 28 '13 at 19:36
-
3Yeah, the Python designers adhere to dogma but they themselves don't respect their own dogma. – Alex Bitek Feb 05 '13 at 07:07
-
3
Something missing from the rest of the answers here: the len
function checks that the __len__
method returns a non-negative int
. The fact that len
is a function means that classes cannot override this behaviour to avoid the check. As such, len(obj)
gives a level of safety that obj.len()
cannot.
Example:
>>> class A:
... def __len__(self):
... return 'foo'
...
>>> len(A())
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
len(A())
TypeError: 'str' object cannot be interpreted as an integer
>>> class B:
... def __len__(self):
... return -1
...
>>> len(B())
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
len(B())
ValueError: __len__() should return >= 0
Of course, it is possible to "override" the len
function by reassigning it as a global variable, but code which does this is much more obviously suspicious than code which overrides a method in a class.

- 47,440
- 4
- 68
- 97
-
3It also checks that the int is not greater than `sys.maxsize`, and that `obj.__len__` exists in the first place. I wrote [an answer on another question](https://stackoverflow.com/a/59604139/4518341) that lists all the different checks. – wjandrea Jul 04 '20 at 18:59
There are some great answers here, and so before I give my own I'd like to highlight a few of the gems (no ruby pun intended) I've read here.
- Python is not a pure OOP language -- it's a general purpose, multi-paradigm language that allows the programmer to use the paradigm they are most comfortable with and/or the paradigm that is best suited for their solution.
- Python has first-class functions, so
len
is actually an object. Ruby, on the other hand, doesn't have first class functions. So thelen
function object has it's own methods that you can inspect by runningdir(len)
.
If you don't like the way this works in your own code, it's trivial for you to re-implement the containers using your preferred method (see example below).
>>> class List(list):
... def len(self):
... return len(self)
...
>>> class Dict(dict):
... def len(self):
... return len(self)
...
>>> class Tuple(tuple):
... def len(self):
... return len(self)
...
>>> class Set(set):
... def len(self):
... return len(self)
...
>>> my_list = List([1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'])
>>> my_dict = Dict({'key': 'value', 'site': 'stackoverflow'})
>>> my_set = Set({1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'})
>>> my_tuple = Tuple((1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F'))
>>> my_containers = Tuple((my_list, my_dict, my_set, my_tuple))
>>>
>>> for container in my_containers:
... print container.len()
...
15
2
15
15

- 159,742
- 34
- 281
- 339

- 4,307
- 1
- 15
- 14
-
You forgot to re-implement String, we like to know the length of those quite often ;) If one is the kind of person who wish to bend the language at its likings, this person will be more comfortable in Ruby, where he can add and overload methods to existing classes. Instead of defining a new class to add just one method. bye – Nicola Mingotti Aug 05 '23 at 21:11