Behaviour of list comprehensions

Steven D'Aprano steve at pearwood.info
Tue Feb 2 08:58:22 EST 2016


Hi Arsh, and welcome!

On Wed, 3 Feb 2016 12:30 am, arsh.py at gmail.com wrote:

> I am having some understandable behaviour from one of my function name
> week_graph_data() which call two functions those return a big tuple of
> tuples, But in function week_graph_data() line no. 30 does not
> work(returns no result in graph or error).
> 
> I have check both functions are called in week_graph_data() individually
> and those run perfectly. (returning tuple of tuples)
> 
> here is my code: pastebin.com/ck1uNu0U

There's no need to waste your time, and other people's time, by making a
pastebin. Since it's less than 30 lines, just include it in your email.

(Be careful with Gmail that it doesn't kill the indentation. Just make sure
you send plain text, with no "rich text" -- actually HTML -- formatting.)



def week_list_func():
    """ A function returning list of last 6 days in 3-tuple"""
    date_list = [] 
    for i in xrange(7):
        d=date.today() - timedelta(i)
        t = d.year, d.month, d.day
        date_list.append(t)
    return reversed(date_list)

def week_graph_data():
    day_list_inbox = inbox_week()  # returns big Tuple of tuples   
    day_list_outbox = outbox_week() # Same as inbox_week()
    dates_inbox = tuple(a[:-7] for a in day_list_inbox)
    dates_outbox = tuple(a[:-7] for a in day_list_outbox)
    week_list = week_list_func()
    bar_chart = pygal.Bar()
    bar_chart.title = 'Weekly Email Analysis'
    bar_chart.x_labels = (list(week_list_func()))
    bar_chart.add('Received', 
            [sum(t==i for t in dates_outbox) for i in list(week_list)]
            )
    bar_chart.add('Sent', 
            [sum(m==n for n in dates_inbox) for m in list(week_list)]
            )
    week_chart = bar_chart.render(is_unicode = True)
    return bar_chart.render_to_file('ok_.svg')

week_graph_data()



Your problem is that week_list_func() returns an iterator, so once you
convert it to a list the first time, it becomes empty. For example:


py> values = [1, 2, 3, 4, 5, 6, 7]
py> days = reversed(values)
py> print days
<listreverseiterator object at 0xb7e578ac>
py> print list(days)
[7, 6, 5, 4, 3, 2, 1]
py> print list(days)
[]


Here, days is an iterator. Once you consume the iterator completely the
first time, there's nothing left, so the second time you get an empty list.

You can fix this by having week_list_func() return a list or tuple:


# Version 1
def week_list_func():
    """ A function returning list of last 6 days in 3-tuple"""
    date_list = [] 
    for i in xrange(7):
        d=date.today() - timedelta(i)
        t = d.year, d.month, d.day
        date_list.append(t)
    return date_list[::-1]  # reverse the list with a slice


# Version 2
def week_list_func2():
    """ A function returning list of last 6 days in 3-tuple"""
    date_list = [] 
    for i in xrange(6, -1, -1):
        d=date.today() - timedelta(i)
        t = d.year, d.month, d.day
        date_list.append(t)
    return date_list


Because this function returns an actual list, there is no need to call
list() on the result.


-- 
Steven



More information about the Python-list mailing list