The built-in >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function works on some objects, but not on others. Only things that have a length work with the >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function.
Lists, sets, dictionaries, strings, and most data structures in Python have a length:
>>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> len(numbers) 7
But numbers don't:
>>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len()
When making a class in Python, you can control whether instances of that class have a length.
Python's built-in >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function calls the >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 6 method (pronounced "dunder >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1") on the object you give it.
So if that object has a >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 6 method, it has a length:
>>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7
If it doesn't have a >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 6 method, the >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function raises a >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 1 instead:
Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len()
How to make instances of your class have a length?
Python's >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 2 module has a function (>>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 3) which can randomly select an item from a given sequence.
>>> import random >>> colors = ['red', 'blue', 'green', 'purple'] >>> random.choice(colors) 'purple'
This >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 3 function only works on objects that can be indexed and have a length.
Here we have a class named >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 5:
class ForgivingIndexer: def __init__(self, sequence): self.sequence = sequence def __getitem__(self, index): return self.sequence[int(index)]
This class has a >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 6 method and a >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 7 method. That >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 7 method allows instances of this class to be indexed using square brackets (>>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 9).
But this isn't quite enough to allow our >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 5 objects to work with the Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function. If we pass a >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 5 object to the Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function, we'll get an error:
>>> import random >>> fruits = ForgivingIndexer(['apple', 'lime', 'pear', 'watermelon']) >>> random.choice(fruits) Traceback (most recent call last): File "", line 1, in File "/usr/lib/python3.10/random.py", line 378, in choice return seq[self._randbelow(len(seq))] TypeError: object of type 'ForgivingIndexer' has no len()
Python gives us an error because >>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> numbers.__len__() 7 5 objects don't have a length, which the Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function requires. These objects don't work with the built-in >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function:
>>> fruits = ForgivingIndexer(['apple', 'lime', 'pear', 'watermelon']) >>> len(fruits) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'ForgivingIndexer' has no len()
In order to support the built-in >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function, we can add a >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 6 method to this class:
def __len__(self): return len(self.sequence)
Now instances of this class have a length:
>>> import random >>> fruits = ForgivingIndexer(['apple', 'lime', 'pear', 'watermelon']) >>> len(fruits) 4
And they also work with Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1:
>>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 0
Summary
You can make your objects work with the built-in >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 1 function by adding a >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 6 method to them. You'll pretty much only ever add a >>> n = 10 >>> len(n) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() 6 method if you're making a custom data structure, like a sequence or a mapping.