Search

The Hidden Gems Of Python: Text Automation & Generators

Did you Know: We can use generators/coroutines in place of multi-threading?

Most of us don't think twice about the simple for loop or how it works. Why should we? Is there anything behind it? How does it work? Let's take a look behind the scenes. Python's for loop is really a for each loop (for each element in collection).

msg = "The quick brown fox jumps over the lazy dog"

If we want to traverse the string above to produce each letter one by one, we simply treat this string like any other sequence in python.

for letter in msg:
    print letter

'T h e q u i c k b r o w n .... lazy dog...

Outcomes our string one letter at a time to the standard output. So what is the for loop actually doing for us? Just as you would assume, as if we were to consume an iterator manually.

iterator = iter(msg)
iterator.next()
T
iterator.next()
h
iterator.next()
e
...iterator.next()
d
iterator.next()
o
iterator.next()
g

There is no hasNext method in python we... A StopIteration exception is thrown when we reach the end of our string.

In other form:
def consume_iterator(file):
    try:
        with open(file) as f:
        while(True):
            line = next(f)
            print line,
    except StopIteration:
        print "End of Iteration" #could return None
 
 
We say here the for loop consumes an iterator for us. With that said, let's move to the second part of this demonstration and build an automated typewriter...

In the next section, we are going to build a generator which automates the typing of text to our standard output. First, we create our generator.
 
The code below uses our generator to yield one value at a time and pause for some interval of time to mimic that of typing on a keyboard.

#Automated Typewriter:
#Python 2.7
from sys import stdout
from time import sleep

def get_letter(msg):
    for i in msg:
        yield i

def typewrite(msg, interval = .1, play = True):
    gen = get_letter(msg)
    while(play):
        try:
            word = stdout.write("%s" % gen.next())
            stdout.flush()
            sleep(interval)
       except StopIteration:
           play = False
           stdout.write("\n")

By using keyword yield we automatically turn function get_letter into a generator (can also use (x for x in msg) similar to that of a list comprehension).

#file: java_class.txt
public class Demo {
    public class Demo() {
        public static void main (String [] args){
               System.out.println("Hello World");
    }
}


file = open('Desktop/java_class.txt')
msg = file.read()
typewrite(msg, .1)
if (isMyPost) { }