Ali
Ali

Reputation: 1041

initializing members of a list

I want to initialize a list in python. I do not understand why the code below does not work:

u = ['abc', 'de', 'fghi', 'jklm', 'n', '']
for item in u:
 item = len(item)

There are other ways to initialize the list, like:

u = [len(item) for item in u]

But, my question is why the first code does not work.

Edit: I am a newbie to Python, and programming. Unfortunately I do not understand some parts of your answers. For example:
- rebinding in "rebinding the name item to the length of the name item "
- iterator in "item" is a temporary variable that points to an element of a u based on where the (implicit) iterator is pointing
As far as I understand, my second example, creates a new_list in memory, and assigns the values of new_list to u. No matter what the previous values were. But I want to know how I can change the values, in the first list. Thanks

Upvotes: 7

Views: 562

Answers (6)

Bor
Bor

Reputation: 189

item is just a name. in the for loop:

for item in u:

the item is a reference to the object to which u[i] refers. In other words, item and u[i] refer to the same object.

but this statement:

item = len(item)

change the name item to refer to a int, whose value is len(item).

So nothing changed in the list u.

The list comprehension:

u = [len(item) for item in u]

is just create a new list, and the name u is now a reference to the new list.

If you want to use for loop, you can use the enumerate statement:

for i, item in enumerate(u):
    u[i] = len(item)

That changes the referrings of the items of u one by one.

Upvotes: 0

Shashank
Shashank

Reputation: 13869

The reason the first code doesn't work is because item is just a reference to each iterable object in the sequence u. When you say item = len(item) you actually do assign len(item) to item, but since item was just acting as a reference pointer pointing to u[i] for the i*th* step in your loop, it won't actually change u[i] itself.

To change u[i] you can do list comprehension like you showed in your question, or do something like:

for i in range(len(u)):
    u[i] = len(u[i])

A third way is the very useful enumerate method introduced in python 2.3.

for i, item in enumerate(u):
    u[i] = len(item)

Enumerate returns a list of tuples created from its argument (don't quote me on this...but it basically acts as a list of tuples) where each tuple inside is of the form (index, argument[index]).

Upvotes: 1

Andrew Clark
Andrew Clark

Reputation: 208475

You cannot change the contents of a list just by assigning a new value to a name that represents an entry in that list. You need to use index assignment, for example to change the first entry in the list to 'foo' you could do u[0] = 'foo'.

In this case you could do something like the following (although the list comprehension from you question is cleaner):

for i, item in enumerate(u):
    u[i] = len(item)

Note that if the items in your list are mutable you can modify the element directly, you just can't reassign them. For example with a list of lists:

u = [['a'], ['b', 'c']]
for item in u:
    item.append(len(item))
# u is now [['a', 1], ['b', 'c', 2]]

Upvotes: 1

Mike Vella
Mike Vella

Reputation: 10575

The first code does work. The list u is initialized in the first line and the next two lines execute having no effect on the rest of the code - there's no point to them.

u = ['abc', 'de', 'fghi', 'jklm', 'n', '']

Is initializing the list u with contents ['abc', 'de', 'fghi', 'jklm', 'n', ''] - that's all you need to do to initialize a list.

The lines

for item in u:
    item = len(item)

Just bind the name item to all the values in u immediately after rebind item to the length property of the value one-by-one until the interpreter has worked through the whole list.

Upvotes: 0

Manoj Pandey
Manoj Pandey

Reputation: 4666

In the first case, you are not initializing anything. "item" is a temporary variable that points to an element of a u based on where the (implicit) iterator is pointing. If you want to initialize a list in the first style, you can do so as:

u = ['abc', 'de', 'fghi', 'jklm', 'n', '']
v = []
for item in u:
     v.append(len(item))
print v

Upvotes: 4

Phillip Cloud
Phillip Cloud

Reputation: 25662

You're rebinding the name item to the length of the name item that was just bound by the loop. You cannot initialize a list in this way. All you're doing is rebinding a variable in each iteration. Your list comprehension is a perfectly acceptable method for initializing a list.

Upvotes: 3

Related Questions