\[ [Index](index.md) | [Exercise 8.1](ex8_1.md) | [Exercise 8.3](ex8_3.md) \]

# Exercise 8.2

*Objectives:*

- Using generators to set up processing pipelines

*Files Created:* `ticker.py`

**Note**

For this exercise the `stocksim.py` program should still be
running in the background.  You're going to use the `follow()`
function you wrote in the previous exercise.

## (a) Setting up a processing pipeline

A major power of generators is that they allow you to create programs
that set up processing pipelines--much like pipes on Unix systems.
Experiment with this concept by performing these steps:

```python
>>> from follow import follow
>>> import csv
>>> lines = follow('Data/stocklog.csv')
>>> rows = csv.reader(lines)
>>> for row in rows:
        print(row)

['BA', '98.35', '6/11/2007', '09:41.07', '0.16', '98.25', '98.35', '98.31', '158148']
['AA', '39.63', '6/11/2007', '09:41.07', '-0.03', '39.67', '39.63', '39.31', '270224']
['XOM', '82.45', '6/11/2007', '09:41.07', '-0.23', '82.68', '82.64', '82.41', '748062']
['PG', '62.95', '6/11/2007', '09:41.08', '-0.12', '62.80', '62.97', '62.61', '454327']
...
```

Well, that's interesting.  What you're seeing here is that the output of the
`follow()` function has been piped into the `csv.reader()` function and we're
now getting a sequence of split rows.   

## (b) Making more pipeline components

In a file `ticker.py`, define the following class (using your structure code from before) and set up
a pipeline:

```python
# ticker.py

from structure import Structure

class Ticker(Structure):
    name = String()
    price = Float()
    date = String()
    time = String()
    change = Float()
    open = Float()
    high = Float()
    low = Float()
    volume = Integer()

if __name__ == '__main__':
    from follow import follow
    import csv
    lines = follow('Data/stocklog.csv')
    rows = csv.reader(lines)
    records = (Ticker.from_row(row) for row in rows)
    for record in records:
        print(record)
```

When you run this, you should see some output like this:

    Ticker('IBM',103.53,'6/11/2007','09:53.59',0.46,102.87,103.53,102.77,541633)
    Ticker('MSFT',30.21,'6/11/2007','09:54.01',0.16,30.05,30.21,29.95,7562516)
    Ticker('AA',40.01,'6/11/2007','09:54.01',0.35,39.67,40.15,39.31,576619)
    Ticker('T',40.1,'6/11/2007','09:54.08',-0.16,40.2,40.19,39.87,1312959)

## (c) Keep going

Oh, you can do better than that.  Let's plug this into your table generation code. Change
the program to the following:

```python
# ticker.py
...

if __name__ == '__main__':
    from follow import follow
    import csv
    from tableformat import create_formatter, print_table

    formatter = create_formatter('text')

    lines = follow('Data/stocklog.csv')
    rows = csv.reader(lines)
    records = (Ticker.from_row(row) for row in rows)
    negative = (rec for rec in records if rec.change < 0)
    print_table(negative, ['name','price','change'], formatter)
```

This should produce some output that looks like this:

          name      price     change 
    ---------- ---------- ---------- 
             C      53.12      -0.21 
           UTX      70.04      -0.19 
           AXP      62.86      -0.18 
           MMM      85.72      -0.22 
           MCD      51.38      -0.03 
           WMT      49.85      -0.23 
            KO       51.6      -0.07 
           AIG      71.39      -0.14 
            PG      63.05      -0.02 
            HD      37.76      -0.19 

Now, THAT is crazy! And pretty awesome.

**Discussion**

Some lessons learned: You can create various generator functions and
chain them together to perform processing involving data-flow
pipelines.  

A good mental model for generator functions might be Lego blocks.
You can make a collection of small iterator patterns and start
stacking them together in various ways.  It can be an extremely powerful way to program.

\[ [Solution](soln8_2.md) | [Index](index.md) | [Exercise 8.1](ex8_1.md) | [Exercise 8.3](ex8_3.md) \]

----
`>>>` Advanced Python Mastery  
`...` A course by [dabeaz](https://www.dabeaz.com)  
`...` Copyright 2007-2023  

![](https://i.creativecommons.org/l/by-sa/4.0/88x31.png). This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/)
