758

In Python, is the following the only way to get the number of elements?

arr.__len__()

If so, why the strange syntax?

smci
  • 32,567
  • 20
  • 113
  • 146
Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • I added an explanation about it at [Why is Python's `len` function faster than the `__len__` method?](https://stackoverflow.com/a/69563793/30038) – Vlad Bezden Oct 14 '21 at 00:40

8 Answers8

1257
my_list = [1,2,3,4,5]
len(my_list)
# 5

The same works for tuples:

my_tuple = (1,2,3,4,5)
len(my_tuple)
# 5

And strings, which are really just arrays of characters:

my_string = 'hello world'
len(my_string)
# 11

It was intentionally done this way so that lists, tuples and other container types or iterables didn't all need to explicitly implement a public .length() method, instead you can just check the len() of anything that implements the 'magic' __len__() method.

Sure, this may seem redundant, but length checking implementations can vary considerably, even within the same language. It's not uncommon to see one collection type use a .length() method while another type uses a .length property, while yet another uses .count(). Having a language-level keyword unifies the entry point for all these types. So even objects you may not consider to be lists of elements could still be length-checked. This includes strings, queues, trees, etc.

The functional nature of len() also lends itself well to functional styles of programming.

lengths = map(len, list_of_containers)
Soviut
  • 88,194
  • 49
  • 192
  • 260
  • 35
    len() is a global, builtin function; __len__() is a method that object can implement. len(foo) usually ends up calling foo.__len__(). – Tim Lesher Feb 05 '09 at 21:33
  • @BT: I suspect at least part of the reason for `__len__` vs. `.length()` is that all names that begin and end with double-underscores (dunders) are: 1) Reserved for language use, and 2) Allow the language to bypass normal lookup rules (e.g. the method can be looked up directly on the instance's class w/o checking if the instance has shadowed it with an attribute of the same name). The CPython reference interpreter makes use of #2 to speed up implicit invocation of special methods (doesn't have to go through `__getattribute__` or `__getattr__`, doesn't have to check the instance `dict`, etc.). – ShadowRanger Sep 15 '21 at 01:15
  • In compiled languages this doesn't matter so much, but in an already slow, highly dynamic interpreted language, having core concepts that are used frequently defined in ways that allow them to be optimized better is important. The concept of length is tied to truthiness too, so it comes up when you do `if seq:`; CPython can optimize that to a C lookup through a couple pointers in C structs for `tp_bool`, then if it's not defined, looking up `tp_len`, calling it to get a raw C signed `size_t`, and checking if the result is `0` or non-zero. – ShadowRanger Sep 15 '21 at 01:21
  • Using `.length()` would either reserve a non-reserved name to mean length and apply optimizations to a name that is, on its surface, no different from any other, or not perform such reservations and optimizations, require `if seq.length():` explicitly, and involve multiple `dict` lookups, bound method construction, and creation of Python level `int`s (not merely C level signed `size_t`s) even for built-ins, making a simple "is it empty or non-empty?" test substantially slower (a quick test put it at over 4x longer to call a `length` method as part of a test, vs. just `if seq:`). – ShadowRanger Sep 15 '21 at 01:23
54

The way you take a length of anything for which that makes sense (a list, dictionary, tuple, string, ...) is to call len on it.

l = [1,2,3,4]
s = 'abcde'
len(l) #returns 4
len(s) #returns 5

The reason for the "strange" syntax is that internally python translates len(object) into object.__len__(). This applies to any object. So, if you are defining some class and it makes sense for it to have a length, just define a __len__() method on it and then one can call len on those instances.

nosklo
  • 217,122
  • 57
  • 293
  • 297
rz.
  • 19,861
  • 10
  • 54
  • 47
26

Just use len(arr):

>>> import array
>>> arr = array.array('i')
>>> arr.append('2')
>>> arr.__len__()
1
>>> len(arr)
1
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
Tim Lesher
  • 6,341
  • 2
  • 28
  • 42
24

The preferred way to get the length of any python object is to pass it as an argument to the len function. Internally, python will then try to call the special __len__ method of the object that was passed.

David Locke
  • 17,926
  • 9
  • 33
  • 53
24

Python uses duck typing: it doesn't care about what an object is, as long as it has the appropriate interface for the situation at hand. When you call the built-in function len() on an object, you are actually calling its internal __len__ method. A custom object can implement this interface and len() will return the answer, even if the object is not conceptually a sequence.

For a complete list of interfaces, have a look here: http://docs.python.org/reference/datamodel.html#basic-customization

UncleZeiv
  • 18,272
  • 7
  • 49
  • 77
8

you can use len(arr) as suggested in previous answers to get the length of the array. In case you want the dimensions of a 2D array you could use arr.shape returns height and width

Ahmed Abobakr
  • 1,618
  • 18
  • 26
7

len(list_name) function takes list as a parameter and it calls list's __len__() function.

Harun ERGUL
  • 5,770
  • 5
  • 53
  • 62
3

Python suggests users use len() instead of __len__() for consistency, just like other guys said. However, There're some other benefits:

For some built-in types like list, str, bytearray and so on, the Cython implementation of len() takes a shortcut. It directly returns the ob_size in a C structure, which is faster than calling __len__().

If you are interested in such details, you could read the book called "Fluent Python" by Luciano Ramalho. There're many interesting details in it, and may help you understand Python more deeply.

JOHNKYON
  • 83
  • 1
  • 7