2

I have a list called 'mb', its format is:

['Company Name', 'Rep', Mth 1 Calls, Mth 1 Inv Totals, Mth 1 Inv Vol, Mth 2 

...And so on

In the below code I simply append a new list of 38 0's. This is fine.

However in the next line I get an error: 'generator' object does not support item assignment

Can anyone tell me: 1) how to correct this error, and 2) why len(mb)-1 below is considered a generator.

Note: row[0] is merely a 'Company Name' held in another list.

mb.append(0 for x in range(38))
mb[len(mb)-1][0]=row[0]
aIKid
  • 26,968
  • 4
  • 39
  • 65
Phoenix
  • 4,386
  • 10
  • 40
  • 55

2 Answers2

9

In fact, you do not append a list of 38 0s: you append a generator that will yield 0 38 times. This is not what you want. However, you can change can change mb.append(0 for x in range(38)) to

mb.append([0 for x in range(38)]) 
# note the [] surrounding the original generator expression!  This turns it
# into a list comprehension.

or, more simply (thanks to @John for pointing this out in the comments)

mb.append([0] * 38)
Cody Piersall
  • 8,312
  • 2
  • 43
  • 57
  • 2
    Or `mb.extend([0]*38)`, but does that fix the OP's problem? – John Zwinck Nov 21 '13 at 14:45
  • @JohnZwinck Oops, I didn't realize the OP actually wanted to append a list of 0s. Silly me. – Cody Piersall Nov 21 '13 at 14:47
  • Doesn't that create a list with 1 element which contains 38 times 0? I think you need to use `.extend()` – Aaron Digulla Nov 21 '13 at 14:50
  • @AaronDigulla, no it contains a list with 38 elements each of which is 0. Multiplying a list repeats the elements in the list it doesn't change the actual elements. – Duncan Nov 21 '13 at 15:06
  • @Duncan: That's wrong. I tried to the code above both on Python2 and 3 and I always get len(mb) == 1. – Aaron Digulla Nov 21 '13 at 15:28
  • @AaronDigulla Was I misinterpreting the OP? I thought he wanted to append a single item--a list--with 38 `0`s? You changed my code to add 38 elements to his list. – Cody Piersall Nov 21 '13 at 15:33
  • I'm rolling the answer back; I think the OP actually wants to append a single list with 38 elements, not append 38 elements to his original list. Feel free to roll it back again if it turns out I'm wrong. – Cody Piersall Nov 21 '13 at 15:40
  • Thanks for all your replies, I was looking to add a list of 38 zero elements. I am still uncertain as to this movement from generator to list comprehension if someone can offer an answer or effective reading material. – Phoenix Nov 21 '13 at 16:13
  • @Robert The terms are kind of hard to get your head around at first. A "list comprehension" creates a list, so you can do regular list-y things with it: index, append, etc. A "generator expression" creates a generator, which you can't index or anything. You can do a for loop on it, and it will only return (actually, _yield_) the items **as you need them**. Here's a good answer about iterables in general: http://stackoverflow.com/a/231855/1612701 – Cody Piersall Nov 21 '13 at 16:27
5

You should do this instead:

mb.extend([0]*38)

That way you are appending 38 zeros, rather than appending a single generator expression given by range() (n.b. in Python 2 that gave a list instead).

And using extend instead of append makes the list longer by 38 instead of making it longer by 1 and having the 1 new element be a list of 38 zeros.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436