2251

How do I get the number of elements in the list items?

items = ["apple", "orange", "banana"]

# There are 3 items.
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
y2k
  • 65,388
  • 27
  • 61
  • 86
  • 33
    You are obviously asking for the number of elements in the list. If a searcher comes here looking for the size of the object in memory, this is the actual question & answers they are looking for: [How do I determine the size of an object in Python?](http://stackoverflow.com/q/449560/541136) – Russia Must Remove Putin Oct 31 '16 at 14:37
  • 2
    @RussiaMustRemovePutin The title of this question was subsequently edited, so it seems unlikely that people with that question would end up here as it stands. – Karl Knechtel Oct 15 '22 at 06:35

11 Answers11

2926

The len() function can be used with several different types in Python - both built-in types and library types. For example:

>>> len([1, 2, 3])
3
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
gnud
  • 77,584
  • 5
  • 64
  • 78
305

How do I get the length of a list?

To find the number of elements in a list, use the builtin function len:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

And now:

len(items)

returns 3.

Explanation

Everything in Python is an object, including lists. All objects have a header of some sort in the C implementation.

Lists and other similar builtin objects with a "size" in Python, in particular, have an attribute called ob_size, where the number of elements in the object is cached. So checking the number of objects in a list is very fast.

But if you're checking if list size is zero or not, don't use len - instead, put the list in a boolean context - it is treated as False if empty, and True if non-empty.

From the docs

len(s)

Return the length (the number of items) of an object. The argument may be a sequence (such as a string, bytes, tuple, list, or range) or a collection (such as a dictionary, set, or frozen set).

len is implemented with __len__, from the data model docs:

object.__len__(self)

Called to implement the built-in function len(). Should return the length of the object, an integer >= 0. Also, an object that doesn’t define a __nonzero__() [in Python 2 or __bool__() in Python 3] method and whose __len__() method returns zero is considered to be false in a Boolean context.

And we can also see that __len__ is a method of lists:

items.__len__()

returns 3.

Builtin types you can get the len (length) of

And in fact we see we can get this information for all of the described types:

>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list, 
                                            range, dict, set, frozenset))
True

Do not use len to test for an empty or nonempty list

To test for a specific length, of course, simply test for equality:

if len(items) == required_length:
    ...

But there's a special case for testing for a zero length list or the inverse. In that case, do not test for equality.

Also, do not do:

if len(items): 
    ...

Instead, simply do:

if items:     # Then we have some items, not empty!
    ...

or

if not items: # Then we have an empty list!
    ...

I explain why here but in short, if items or if not items is more readable and performant than other alternatives.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
79

While this may not be useful due to the fact that it'd make a lot more sense as being "out of the box" functionality, a fairly simple hack would be to build a class with a length property:

class slist(list):
    @property
    def length(self):
        return len(self)

You can use it like so:

>>> l = slist(range(10))
>>> l.length
10
>>> print l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Essentially, it's exactly identical to a list object, with the added benefit of having an OOP-friendly length property.

As always, your mileage may vary.

Naftuli Kay
  • 87,710
  • 93
  • 269
  • 411
  • 27
    just so you know, you can just do `length = property(len)` and skip the one line wrapper function and keep the documentation / introspection of `len` with your property. – Tadhg McDonald-Jensen Jun 13 '16 at 02:17
28

Besides len you can also use operator.length_hint (requires Python 3.4+). For a normal list both are equivalent, but length_hint makes it possible to get the length of a list-iterator, which could be useful in certain circumstances:

>>> from operator import length_hint
>>> l = ["apple", "orange", "banana"]
>>> len(l)
3
>>> length_hint(l)
3

>>> list_iterator = iter(l)
>>> len(list_iterator)
TypeError: object of type 'list_iterator' has no len()
>>> length_hint(list_iterator)
3

But length_hint is by definition only a "hint", so most of the time len is better.

I've seen several answers suggesting accessing __len__. This is all right when dealing with built-in classes like list, but it could lead to problems with custom classes, because len (and length_hint) implement some safety checks. For example, both do not allow negative lengths or lengths that exceed a certain value (the sys.maxsize value). So it's always safer to use the len function instead of the __len__ method!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MSeifert
  • 145,886
  • 38
  • 333
  • 352
14

And for completeness (primarily educational), it is possible without using the len() function. I would not condone this as a good option DO NOT PROGRAM LIKE THIS IN PYTHON, but it serves a purpose for learning algorithms.

def count(list):   # list is an iterable object but no type checking here!
    item_count = 0
    for item in list:
        item_count += 1
    return item_count

count([1,2,3,4,5])

(The list object must be iterable, implied by the for..in stanza.)

The lesson here for new programmers is: You can’t get the number of items in a list without counting them at some point. The question becomes: when is a good time to count them? For example, high-performance code like the connect system call for sockets (written in C) connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);, does not calculate the length of elements (giving that responsibility to the calling code). Notice that the length of the address is passed along to save the step of counting the length first? Another option: computationally, it might make sense to keep track of the number of items as you add them within the object that you pass. Mind that this takes up more space in memory. See Naftuli Kay‘s answer.

Example of keeping track of the length to improve performance while taking up more space in memory. Note that I never use the len() function because the length is tracked:

class MyList(object):
    def __init__(self):
        self._data = []
        self.length = 0 # length tracker that takes up memory but makes length op O(1) time
        

        # the implicit iterator in a list class
    def __iter__(self):
        for elem in self._data:
            yield elem
            
    def add(self, elem):
        self._data.append(elem)
        self.length += 1
            
    def remove(self, elem):
        self._data.remove(elem)
        self.length -= 1
            
mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
print(mylist.length) # 3
mylist.remove(3)
print(mylist.length) # 2
Jonathan Komar
  • 2,678
  • 4
  • 32
  • 43
  • 2
    Why `for item in list[:]:`? Why not `for item in list:`? Also, I'd use `+= 1` to increment. – Granny Aching Apr 30 '19 at 19:13
  • 4
    If we're going down the rabbit hole of "don't do this but it's fun", I offer `length = max(enumerate(list))[0] + 1`. – Kirk Strauser Dec 08 '20 at 21:56
  • 2
    @KirkStrauser Haha, I laughed at this clever avoidance on `len()` – Jonathan Komar May 15 '21 at 19:51
  • 1
    @JonathanKomar: The `[:]` in `list[:]` is not a "range specifier", that's slicing, which shallow copies the entire `list` for no reason. If you omitted the `[:]`, it would not perform any such wasteful copies; it's not "beneficial to know it is implied", because it's *not* implied at all. I have no idea what "A list type [] is inferred as well" is supposed to mean, but there's no inferred types; the objects have types, and anything meeting the duck-typing requirements of what you've done will be accepted (be it `list`, `tuple`, `str`, etc.). – ShadowRanger Jan 21 '23 at 03:27
  • @ShadowRanger As emphasized, "DO NOT PROGRAM LIKE THIS IN PYTHON [...] purpose for learning algorithms", you shouldn't be analyzing this answer for performance. I am happy you understand what is going on. I'll adjust the answer in this case. – Jonathan Komar Jan 22 '23 at 19:22
10

Answering your question as the examples also given previously:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

print items.__len__()
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shai Alon
  • 969
  • 13
  • 21
  • 20
    In Python, names that start with underscores are semantically non-public methods and should not be used by users. – Russia Must Remove Putin Oct 26 '16 at 15:10
  • 3
    1. `__foo__`: this is just a convention, a way for the Python system to use names that won't conflict with user names. 2. `_foo`: this is just a convention, a way for the programmer to indicate that the variable is private (whatever that means in Python). 3. `__foo`: this has real meaning: the interpreter replaces this name with `_classname__foo` as a way to ensure that the name will not overlap with a similar name in another class. * No other form of underscores have meaning in the Python world. * There's no difference between class, variable, global, etc in these conventions. – Shai Alon Dec 04 '16 at 16:30
  • 6
    This Q&A explains why you shouldn't use the special methods directly as a user: http://stackoverflow.com/q/40272161/541136 – Russia Must Remove Putin Dec 04 '16 at 18:42
  • @AaronHall but for len function it's almost the same. It might be faster for very large variables. However, I get your point and we should use len(obj) and not obj.__len__(). – Shai Alon Feb 28 '17 at 11:39
6

You can use the len() function to find the length of an iterable in python.

my_list = [1, 2, 3, 4, 5]
print(len(my_list))  # OUTPUT: 5

The len() function also works with strings:

my_string = "hello"
print(len(my_string))  # OUTPUT: 5

So to conclude, len() works with any sequence or collection (or any sized object that defines __len__).

Alan Bagel
  • 818
  • 5
  • 24
5

There is an inbuilt function called len() in python which will help in these conditions.

>>> a = [1,2,3,4,5,6]
>>> len(a)  # Here the len() function counts the number of items in the list.
6

This will work slightly different in the case of string: it counts the characters.

>>> a = "Hello"
>>> len(a)
5
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Code Carbonate
  • 640
  • 10
  • 18
  • Saying it "counts" might be misleading because in most cases, it'll just be retrieving an integer that's already defined on the object, not iterating through and incrementing a number like "counts" implies. – wjandrea Jan 21 '23 at 19:17
5

There are three ways that you can find the length of the elements in the list. I will compare the 3 methods with performance analysis here.

Method 1: Using len()

items = []
items.append("apple")
items.append("orange")
items.append("banana")

print(len(items))

output:

3

Method 2: Using Naive Counter Method

items = []
items.append("apple")
items.append("orange")
items.append("banana")

counter = 0
for i in items:
    counter = counter + 1

print(counter)

output:

3

Method 3: Using length_hint()

items = []
items.append("apple")
items.append("orange")
items.append("banana")

from operator import length_hint
list_len_hint = length_hint(items)
print(list_len_hint)

output:

3

Performance Analysis – Naive vs len() vs length_hint()

Note: In order to compare, I am changing the input list into a large set that can give a good amount of time difference to compare the methods.

items = list(range(100000000))

# Performance Analysis
from operator import length_hint
import time

# Finding length of list
# using loop
# Initializing counter

start_time_naive = time.time()
counter = 0
for i in items:
    # incrementing counter
    counter = counter + 1
end_time_naive = str(time.time() - start_time_naive)

# Finding length of list
# using len()
start_time_len = time.time()
list_len = len(items)
end_time_len = str(time.time() - start_time_len)

# Finding length of list
# using length_hint()
start_time_hint = time.time()
list_len_hint = length_hint(items)
end_time_hint = str(time.time() - start_time_hint)

# Printing Times of each
print("Time taken using naive method is : " + end_time_naive)
print("Time taken using len() is : " + end_time_len)
print("Time taken using length_hint() is : " + end_time_hint)

Output:

Time taken using naive method is : 7.536813735961914
Time taken using len() is : 0.0
Time taken using length_hint() is : 0.0

Conclusion

It can be clearly seen that time taken for naive is very large compared to the other two methods, hence len() & length_hint() is the best choice to use.

Tamil Selvan
  • 1,600
  • 1
  • 9
  • 25
  • 1
    This is *terrible* micro-benchmarking code. A single execution timed with `time.time()`? Learn to use the `timeit` module; there are *so* many confounding variables that it's impossible to draw any conclusions from your test beyond "of course looping and counting is slower". – ShadowRanger Jan 21 '23 at 03:37
4

Simple: use len(list) or list.__len__()

In terms of how len() actually works, this is its C implementation:

static PyObject *
builtin_len(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
    Py_ssize_t res;

    res = PyObject_Size(obj);
    if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }
    return PyLong_FromSsize_t(res);
}

Py_ssize_t is the maximum length that the object can have. PyObject_Size() is a function that returns the size of an object. If it cannot determine the size of an object, it returns -1. In that case, this code block will be executed:

    if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }

And an exception is raised as a result. Otherwise, this code block will be executed:

    return PyLong_FromSsize_t(res);

res which is a C integer, is converted into a Python int (which is still called a "Long" in the C code because Python 2 had two types for storing integers) and returned.

Alec
  • 8,529
  • 8
  • 37
  • 63
  • 5
    Why does knowing, or knowing about the C implementation matter? – cs95 Jun 05 '19 at 03:37
  • Since this question isn't specific to CPython this answer may be misleading. PyPy, IronPython, ... can and do implement it differently. – MSeifert Nov 15 '19 at 08:16
  • This isn't a useful answer, as it's just saying "`len` calls `PyObject_Size()`" and doesn't say what that does, which is "`PyObject_Size()` [calls](https://github.com/python/cpython/blob/ace3f9a0ce7b9fe8ae757fdd614f1e7a171f92b0/Objects/abstract.c#L52) the [`sq_length`](https://docs.python.org/3/c-api/typeobj.html#c.PySequenceMethods.sq_length) or [PyMapping_Size](https://docs.python.org/3/c-api/mapping.html#c.PyMapping_Size) on the passed in object." – Boris Verkhovskiy Jan 12 '21 at 17:12
4

To get the number of elements in any sequential objects, your goto method in Python is len() eg.

a = range(1000) # range
b = 'abcdefghijklmnopqrstuvwxyz' # string
c = [10, 20, 30] # List
d = (30, 40, 50, 60, 70) # tuple
e = {11, 21, 31, 41} # set

len() method can work on all the above data types because they are iterable i.e You can iterate over them.

all_var = [a, b, c, d, e] # All variables are stored to a list
for var in all_var:
    print(len(var))

A rough estimate of the len() method

def len(iterable, /):
    total = 0
    for i in iterable:
        total += 1
    return total
Comsavvy
  • 630
  • 9
  • 18
  • *"any iterable"* -- That's incorrect. I think you mean "any sequence". Generators, for example: `len(x for x in range(8))` -> `TypeError: object of type 'generator' has no len()`. – wjandrea Jun 24 '21 at 14:05
  • There is a slight difference between iterator and iterable. All iterators are iterable but not the otherwise. Kindly refer to this article for more explanation https://www.geeksforgeeks.org/python-difference-iterable-iterator/amp/ – Comsavvy Jul 12 '22 at 09:36
  • @wjandrea: If we're going to be picky, it's any *collection*. Works just fine on `set`s and `dict`s (neither of which are sequences). – ShadowRanger Jan 21 '23 at 03:39
  • @ShadowRanger True, good point, though [the docs](https://docs.python.org/3/library/functions.html#len) say "The argument may be a sequence **or** a collection". On the other hand, if we [follow `collections.abc`](https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes), then any `Sequence` is a `Collection` by definition, but we only need a `Sized` object to get its length. So I think for the sake of this answer, it'd be beter to say "any object" and avoid overcomplicating things. – wjandrea Jan 21 '23 at 18:47
  • After the corrections, this answer is still incorrect with regard to iterables. The `len()` method works on those data types not because they're iterable, but because they have a `__len__()` method, which is to say they have a size that's known ahead of time, before iteration. And I'm not sure how useful that rough estimate is where it actually *does* work on any (finite) iterable. – wjandrea Jan 21 '23 at 18:55