seeker
seeker

Reputation: 558

Behaviour of Python when attempting to iterate over characters in a string

I am attempting to iterate over the following string, using a for loop:

>>> for a,b,c in "cat"
        print(a,b,c)

Now what I intended for this to do was print out each character in the string individually on one physical line, instead I receive an error. I am aware that this is very easily resolved by enclosing the string in the list operator []:

>>> for a,b,c in ["cat"]
        print(a,b,c)
c a t

But could someone explain why this is the case?

Upvotes: 2

Views: 1396

Answers (3)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160377

The for loop goes through each element in the iterable you supply and tries to perform an assignment.

In the first case, since your iterable is 'cat' you're essentially unpacking:

a, b, c = 'c'

during the first iteration and getting the appropriate error message:

ValueError: not enough values to unpack (expected 3, got 1)

because you'll iterate 3 times; once for each character in the string 'cat'.

In the second case, you're unpacking "cat" as expected, because the list has a single element (i.e 'cat') which is retrieved and unpacked into a, b and c.

Upvotes: 3

Martijn Pieters
Martijn Pieters

Reputation: 1121256

You are telling for to expand each iteration value to assign to three separate variables:

for a,b,c in "cat":
#   ^^^^^ the target for the loop variable, 3 different names

However, iteration over a string produces a string with a single character, you can't assign a single character to three variables:

>>> loopiterable = 'cat'
>>> loopiterable[0]  # first element
'c'
>>> a, b, c = loopiterable[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 1)

The error message tells you why this didn't work; you can't take three values out of a string of length 1.

When you put the string into a list, you changed what you loop over. You now have a list with one element, so the loop iterates just once, and the value for the single iteration is the string 'cat'. That string just happens to have 3 characters, so can be assigned to three variables:

>>> loopiterable = ['cat']
>>> loopiterable[0]  # first element
'cat'
>>> a, b, c = loopiterable[0]
>>> a
'c'
>>> b
'a'
>>> c
't'

This still would fail if the contained string has a different number of characters:

>>> for a, b, c in ['cat', 'hamster']:
...     print(a, b, c)
...
c a t
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)

'hamster' is 7 characters, not 3; that's 4 too many.

The correct solution is to just use one variable for the loop target, not 3:

for character in 'cat':
    print(character)

Now you are printing each character separately:

>>> for character in 'cat':
...     print(character)
...
c
a
t

Now, if you wanted to pass all characters of a string to print() as separate arguments, just use * to expand the string to separate arguments to the call:

>>> my_pet = 'cat'
>>> print(*my_pet)
c a t

Upvotes: 7

Feishi
Feishi

Reputation: 669

You are iterating different objects in two blocks of code. In the former one, you iterate the string, which may be considered a special list.

While in the latter one, you iterate the list which contains only one object 'cat'.

You may change the first one to below:

for ch in 'cat':
    print(ch)

Feel free to ask more about this.

Upvotes: 2

Related Questions