The provided web content discusses the concept and implementation of generators in Python, emphasizing their memory efficiency and performance benefits over traditional functions for iterative tasks like generating Fibonacci sequences.
Abstract
Generators in Python are a powerful feature that allows developers to create functions that can return a sequence of values over time rather than computing them all at once and storing them in memory. This is particularly useful for large datasets or memory-intensive operations. The content illustrates this through examples, starting with a traditional Fibonacci function that stores values in a list, and then refining it to use a generator pattern with the yield keyword. The refactored generator function is shown to be more memory-efficient and faster, as it computes each value on-the-fly and does not require the entire sequence to be stored in memory. The article also contrasts generators with strings, demonstrating that strings are not interactable in the same way until they are converted into an iterator using the iter() function. Additionally, the content covers profiling and timing code to quantify the performance gains of using generators. It concludes by encouraging readers to apply this knowledge in their Python coding, with a nod to educational resources and community support.
Opinions
The author believes that generators are superior to traditional functions for certain tasks due to their memory efficiency and performance advantages.
There is an opinion that using generators can significantly improve code execution time, as evidenced by the timing comparison between a traditional function and a generator function.
The author suggests that understanding generators is essential for Python programmers, particularly those working with data science and machine learning.
The content implies that the next() function and the for loop are fundamental tools for interacting with generators, highlighting their importance in Python programming.
The author expresses that sharing knowledge and code examples is valuable for the programming community, as it helps others learn and improve their coding practices.
There is an endorsement of using memory profilers to understand the memory usage of code, which can be crucial for optimizing performance.
The author encourages readers to engage with the provided Colab notebook and Google Drive resources, indicating a belief in the practical benefits of hands-on learning.
The article concludes with a positive outlook on the continued use and exploration of Python's features, suggesting an optimistic view of Python's capabilities and its community's growth.
Generators in Python
Python Review Free Hints — #PySeries#Episode 17
#GENERATORS IN PYTHON: What is it?
Generators in Python allows us towrite a function that can send back a value andthen later resume to pick up whereit left off.
Let’s simplify the code for this lesson, consider this piece of code (Zero out:)
defgen_fibo(n):
a = 1
b = 1
output = []
for i in range(n):
output.append(a)
a,b = b, a + b
returnoutput
The output:
gen_fibo(10)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
These two codes above are not generators.
Let’s get one!
Now using yield keyword in the second fibo function to turn it more memory efficient :-)
03#PyEx — Python — Function — Fibonacci w/ yield:
defgen_fibo(n):
a = 1
b = 1
for i in range(n - 1):
yield a
a, b = a, a + b
The output (a Generator):
g= gen_fibo(10)
g
<generator object gen_fibo at0x7f0cecb33ed0>
As you can see we don’t need to store the information in the list anymore; the two items highlighted in the previous code denounce this. And, more importantly, the insert of the yield keyword instead of the append method… This is the secret of Python generators: working in streaming rather than to store the whole list in memory!
So, it is now a Generator!
Do you see the difference between between those last two codes? No? Fine! So keep reading …
This last function is a Generator. What is a Generator after all?
A Generators it is much more efficient in relation to the use of memory; we are not loading the data completely, in memory, as in the code with append();
We only work in streams (one number at a time), that is, we save only the data that immediately preceding it (we know the formula to generate the next one ;) and thus we are saving memory; the object is much more simpler and efficient:)
Do you want another interactable function to bring the concept home?
Let’s see another generator:
04#PyEx — Python — Function — Simple Generator:
defsimple_gen():
for x inrange (4):
yield x
The output:
g= simple_gen()
g
<generator object simple_gen at0x7f0cecb334d0>
See that the Generator object can be readily interacted with; it is built to be :)
The output:
next(g)0next(g)1next(g)2next(g)3
Fine, Now Are Strings Interactables?
05#PyEx — Python — String —Are interactable?
Now, let’s see if a string object is interactable…
s = ‘hello’
forletterins:
print(letter)
h
e
l
l
o
The output:
next(s)
---------------------------------------------------------------TypeError Traceback (most recent call last)
<ipython-input-262-46f008985a16> in <module>()
1 # Stringisnot interactable:/
----> 2next(s)
TypeError:'str' object is not an iterator
So, Strings are not interactable:/
For transforming Strings into an interactable object use iter() function:
s_iter = iter(s)next(s_iter)
The output:
next(s_iter)'h'next(s_iter)'e'
(...)
06#PyEx — Python — String — Final Code
So, here is the final generator code for our fibonacci function:
The output:
g= prog_fibo_2(10)
g
<generator object gen_fibo_ef at0x7f0cecb34350>
next(g)1next(g)1next(g)2
(...)
And note that it is this very function, next(), that the for loop use internally to bring all the data sequentially and efficiently, and that is cool, right?
The text is released under the CC-BY-NC-ND license, and code is released under the MIT license. If you find this content useful, please consider supporting the work by buying the book!
Now run pip in your Colab Notebook:
07#PyEx — Python — String —Profiling & Timing
pip install memory_profiler
Requirement already satisfied: memory_profiler in /usr/local/lib/python3.7/dist-packages (0.58.0) Requirement already satisfied: psutil in /usr/local/lib/python3.7/dist-packages (from memory_profiler) (5.4.8)
And this profiler:
%load_ext memory_profiler
The memory_profiler extensionis already loaded. To reload it, use: %reload_ext memory_profiler
Running again the original & final code:
defgen_fibo(n):
a = 1
b = 1
output = []
for i in range(n):
output.append(a)
a,b = b, a + b
returnoutput
Timing it:
%timeit gen_fibo(10)
1000000 loops, best of 5: 1.31 µs per loop
The other one:
def prog_fibo_2(n):
a = 1
b = 1for i in range(n):
yield aa, b = b, a + b
Timing it:
%timeit prog_fibo_2(10)
1000000 loops, best of 5: 236 ns per loop
As you can see, the code using the python generator is running in the nanoseconds(10**-9), instead of microseconds(10**-6)
A bit faster, right?
Generators in Python works!
Check it out! Get this under your belt in your next Python code! :b
print(“That’s it! thank you for reading this episode about the wonders of Python:) “)
That's it! thank you for reading this episode about the wonders of Python:)
If you find this post helpful, please consider to subscribe to the Jungletronics for more posts like this.