Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Combo challenge: my code works in workspaces but not in challenge

I got from forum that this challenge should be solved like this:

def combo(my_list, my_string):
  new_list = []

  for index, item in enumerate(my_list):
    tup = item, my_string[index]
    new_list.append(tup)

  return new_list

But I didn't pay needed attention to enumerate func and solved it with more difficult code:

def combo(my_list, my_string):
  if len(my_list) == len(my_string):
    new_list = []
    count = 0
    for item in my_string:
      my_list.append(item)
    while True: 
      new_list.append(tuple(my_list[count::len(my_string)]))  
      count += 1
      if count == len(my_string):
        break
    print(new_list)

but it works only in workspaces and not in challenge. It says: "Didn't get the right output. For example, expected (10, 'T') as the first item, got (10, 'T') instead." Why? I overthinked the code to get it solved, so if anybody knows I will appreciate an answer.

p.s: also appriciate for any feedback of my code

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,468 Points

You are not crazy: your code returns the correct list of tuples results... but with side-effects.

By using the statement my_list.append() the code is modifying one of the input parameters. It is rarely a good practice to modify an input unless that is the purpose of the function. Python passes arguments by reference so my_list is equivalent to the global list passed in.

One fix for your code would be to operate on a copy of my_list:

def combo(my_list, my_string):
    if len(my_list) == len(my_string):
        new_list = []
    my_list_copy = my_list[:] #<-- make a copy
    count = 0
    for item in my_string:
        my_list_copy.append(item) #<-- operate on copy
    while True: 
        new_list.append(tuple(my_list_copy[count::len(my_string)]))          
        count += 1
        if count == len(my_string):
            break
    return new_list

How I would improve your code:

def combo(my_list, my_string):
    # commented out conditional  init. Challenge assumes equal length
    #if len(my_list) == len(my_string):
    #    new_list = []
    new_list = []
    my_list_copy = my_list[:] #<-- make a copy
    for item in my_string:
        my_list_copy.append(item) #<-- operate on copy

    # replace 'while True / count / break' with 'for range'
    # count = 0
    # while True: 
    for count in range(len(my_string)):
        new_list.append(tuple(my_list_copy[count::len(my_string)]))      
        # count += 1
        # if count == len(my_string):
        #     break
    return new_list

Ultimately, the challenge can be solved without loops by using zip:

def combo(my_list, my_string):
    new_list = list(zip(my_list, my_string))
    return new_list
Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

Kenneth Love, the OP code produced the correct return value, but failed due to modifying an input parameter. Can the error message be improved to indicate this is why the code is failing? The current message "Didn't get the right output. For example, expected (10, 'T') as the first item, got (10, 'T') instead." implies it's an output problem instead of a side-effect issue.

Thank's Chris. Using a 'for range' loop is a nice idea, I have not thought about this before. This is why I should get into basics of python more carefully and find out what exactly iterables and iterators are and how they can be used with loops. And thank's a lot about 'side-effects', now I know more how to handle with arguments , if they vary inside of a function.