When working with Python, you might often hear the term "iterables," but what exactly are they, and why should you care? In this article, we'll break down the concept of iterables, explore their significance in memory management, delve into their implementation using the __iter__
function in a class, and showcase their utility through examples and built-in functions.
What Are Iterables?
Iterables are a fundamental concept in Python that allow us to work with a sequence of values, one at a time. In simpler terms, they help us deal with a bunch of items without having to load them all into memory at once. This is a game-changer when handling large data sets or when you want to conserve memory resources.
I still don't understand!
Iterables can be most likened to lists. They provide the same concept for multiple values to be used or looped through.
Why do we use them? It is because of their memory and time efficiency.
Take a look at this! If you were to use a list of 1 hundred numbers, Creating it as a list will eat up memory like crazy. What we can do to avoid that is use the range
function.
This built-in function returns an iterable that will only take it one value at a time and discard every previous value.
Let's see how it will work.
Using the __iter__ Function
Now, let's talk about the inner workings of iterables. In Python, classes can be made iterable by defining the __iter__
method. This method returns an iterator object, which is responsible for keeping track of the current position and providing the next value when requested.
class MyIterable:
def __init__(self, *data):
self.data = data
def __iter__(self):
self.index = 0
return self
def __next__(self):
if self.index < len(self.data):
value = self.data[self.index]
self.index += 1
return value
else:
raise StopIteration
In this example, the MyIterable
class takes a list of data during initialization. The __iter__
method initializes the index to 0, and the __next__
method returns the next value while updating the index until all values are exhausted.
This __next__
function can be modified to do anything apart from just changing the values. In that case, you can run a function only when you get to that particular value of the iterable.
What makes this more memory efficient because it takes it one value at a time and discards it after use
An Example of an implementation of the code above is shown as follows
x = MyIterable(1, 2, 4)
for i in x:
print(i) # prints 1 2 4
Using the yield
keyword
Here is how we can use the yield keyword to implement the same concept
def my_map(func, iterable):
for item in iterable:
yield func(item)
Here the function my_map
is returning the the returned value of the function only when it is called.
The function is paused after every iteration and waits for the next call to return the value.
This is usually called a Generator in python.
Conclusion
Iterables are like a magical tool in Python that enable memory-efficient processing of sequences of data. By processing items one by one, you can tackle large datasets without overwhelming your computer's memory. Some built-in functions work using this concept like range
, map
, filter
, sum
and alot more. The next time you're working with a massive amount of data, remember that iterables are both memory and code efficient.