user2509830
user2509830

Reputation: 93

Python Function Not Working

I am trying to create a function, new_function, that takes a number as an argument. This function will manipulate values in a list based on what number I pass as an argument. Within this function, I will place another function, new_sum, that is responsible for manipulating values inside the list. For example, if I pass 4 into new_function, I need new_function to run new_sum on each of the first four elements. The corresponding value will change, and I need to create four new lists.

example:

listone=[1,2,3,4,5]
def new_function(value):
    for i in range(0,value):
        new_list=listone[:]
        variable=new_sum(i)
        new_list[i]=variable
        return new_list

# running new_function(4) should return four new lists
#    [(new value for index zero, based on new_sum),2,3,4,5]
#    [1,(new value for index one, based on new_sum),3,4,5]
#    [1,2,(new value for index two, based on new_sum),4,5]
#    [1,2,3,(new value for index three, based on new_sum),5]

My problem is that i keep on getting one giant list. What am I doing wrong?

Upvotes: 0

Views: 1236

Answers (2)

abarnert
abarnert

Reputation: 365737

The problem with return new_list is that once you return, the function is done.

You can make things more complicated by accumulating the results and returning them all at the end:

listone=[1,2,3,4,5]
def new_function(value):
    new_lists = []
    for i in range(0,value):
        new_list=listone[:]
        variable=new_sum(i)
        new_list[i]=variable
        new_lists.append(new_list)
    return new_lists

However, this is exactly what generators are for: If you yield instead of return, that gives the caller one value, and then resumes when he asks for the next value. So:

listone=[1,2,3,4,5]
def new_function(value):
    for i in range(0,value):
        new_list=listone[:]
        variable=new_sum(i)
        new_list[i]=variable
        yield new_list

The difference is that the first version gives the caller a list of four lists, while the second gives the caller an iterator of four lists. Often, you don't care about the difference—and, in fact, an iterator may be better for responsiveness, memory, or performance reasons.*

If you do care, it often makes more sense to just make a list out of the iterator at the point you need it. In other words, use the second version of the function, then just writes:

new_lists = list(new_function(4))

By the way, you can simplify this by not trying to mutate new_list in-place, and instead just change the values while copying. For example:

def new_function(value):
    for i in range(value):
        yield listone[:i] + [new_sum(i)] + listone[i+1:]

* Responsiveness is improved because you get the first result as soon as it's ready, instead of only after they're all ready. Memory use is improved because you don't need to keep all of the lists in memory at once, just one at a time. Performance may be improved because interleaving the work can result in better cache behavior and pipelining.

Upvotes: 2

karthikr
karthikr

Reputation: 99630

Fix the indentation of return statement:

listone=[1,2,3,4,5]
def new_function(value):
    for i in range(0,value):
        new_list=listone[:]
        variable=new_sum(i)
        new_list[i]=variable
    return new_list

Upvotes: 7

Related Questions