Thread Shed: Project successful, but confused about a few basic concepts

I just completed the Thread Shed project, I would say 95% unassisted. I feel like many of the concepts are finally sinking in and becoming a more ‘natural’ part of my problem solving process. I am more confident with concepts like iterating with loops, accessing lists by index, manipulating them, etc. However, I feel like I am still haven’t quite cemented a certain basic concept and it is nagging me - even though I can usually pull through with trial and error. I would like to fix this before I proceed any further. I’m going to use the Thread Shed project to illustrate my problems/idiocy.

Lists: Extending, Appending, Concatenating, Splitting

In the Thread Shed project we are asked to create a list of all the threads sold (listed by color), and separate colors instances where 2 or more threads are sold (‘white&blue’ must be entered separately as ‘white’, ‘blue’) . Effectively, we must split a string containing ‘&’ and then add the two resultant strings into a list. The code is as follows:

thread_sold_split = []

for eachcolor in thread_sold:
    #thread_sold_split += eachcolor.split('&')
    thread_sold_split.extend(eachcolor.split('&')) #why does this not work with .append? - adds as lists inside the list

There are 3 different methods that I have tried in the above example. I don’t fully understand why some of them work, and the others don’t.

  1. thread_sold_split += eachcolor.split(’&’)
    Simple concatenation seems to work fine, in this case. Instances in which colors are conjoined (example: ‘white&blue’) are dealt with appropriately. Each color is added as a separate element in the list. The results look like this:

  2. thread_sold_split.extend(eachcolor.split(’&’))
    Using .extend seems to work as well. How I understand this is that extend is the same += above. When a string is split - for example ‘white&blue’ it is returned as a list [white, blue]. Extend takes each element, ‘one-at-a-time’ and adds it to the end of the list being manipulated.

  3. thread_sold_split.append(eachcolor.split(’&’))
    Using .append does not work. I believe what is happening here is that .split() processes each string and returns it as a list. So ‘blue’ is returned as [‘blue’] and white&blue is returned as [‘white’,‘blue’]. These lists are appended and so we get a list of lists. Like so:

At this point I felt like I understood how .append and .extend differ. One of them inserts elements one at a time to the end of the list (extend) while the other dumps a list inside of another list (append).

But this next component left me even more confused.

The next part of the project asks us to create a list of the colors offered. Basically just a unique-element list of the colors available for sale instead of the color of every thread sold. Simple enough. I did it like this:

allcolors = []
for color in thread_sold_split:
    if color not in allcolors:
        allcolors.append(color) #why does this not work with .extend? - adds as individual letters inside the list

Initially I attempted to use .extend. My logic being that I simply want to add a single element (color) to a list. However, using .extend adds the color one letter a time. Why is this behavior so much different that the use of .extend in the first example above - where it appropriately added a single element to a list? I don’t see how the argument being passed is any different. However the results are not the same:

Why does extend work in the first case, but not the second case?

I apologize for the lengthy post. However I feel like it is such a basic concept that I should master now instead of stumbling through it. I appreciate any help. Cheers.

It goes a bit off-kilter as the .extend method doesn’t just work on lists, it works on any sequence and Python allows strings to be treated as sequences (which is nice for things like iteration and slicing amongst others). So what you actually add is each element of the string one by one.

So to boil it down a bit you’d use append whenever you’re adding a single element (such as one entire string) and extend whenever you wanted multiple elements added one by one (such as a list of multiple strings).

In your first example as per your print you had a list of lists and therefore you still had a sequence with mutliple elements. Quick example to explain what I think the difference was-

test = []
test.extend('red')  # effectively iterates through the string (three elements)
# our list is now ... ['r', 'e', 'd']
test = []
test.extend(['red'])  # effectively iterates through  the list (one element)
# our list is now ... ['red']