Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function iterates with print but not with return

Python newbie here, running 2.7.

I am trying to create a program that uses a function to generate text, and then outputs the function-generated text to a file.

When just printing the function in powershell (like this: http://codepad.org/KftHaO6x), it iterates, as I want it to:

def writecode (q, a, b, c):
    while b < q:
        b = b + 1
        print "v%d_%d_%d = pairwise (caps[%d],sals[%d],poss[%d],poss[%d],poss[%d],pos_range)" %(a,b,c,a,a,a,b,c)
        print "votes%d_%d.append(v%d_%d_%d)" % (b,c,a,b,c,)
        print "v%d_%d_%d = pairwise (caps[%d],sals[%d],poss[%d],poss[%d],poss[%d],pos_range)" %(a,c,b,a,a,a,c,b)
        print "votes%d_%d.append(v%d_%d_%d)" % (c,b,a,c,b)

writecode (5,1,0,4)

When trying to output the function into a file (like this: http://codepad.org/8GJpp9QY), it only gives 1 value, i.e. does not iterate:

def writecode (q, a, b, c):
    while b < q:
        b = b + 1
        data_to_write = "v%d_%d_%d = pairwise (caps[%d],sals[%d],poss[%d],poss[%d],poss[%d],pos_range)" %(a,b,c,a,a,a,b,c)
        data_to_write_two = "votes%d_%d.append(v%d_%d_%d)" % (b,c,a,b,c,)
        data_to_write_three = "v%d_%d_%d = pairwise (caps[%d],sals[%d],poss[%d],poss[%d],poss[%d],pos_range)" %(a,c,b,a,a,a,c,b)
        data_to_write_four = "votes%d_%d.append(v%d_%d_%d)" % (c,b,a,c,b)
        return data_to_write
        return data_to_write_two
        return data_to_write_three
        return data_to_write_four

x = writecode (5,1,0,4)

out_file = open("code.txt", "a")
out_file.write(x)
out_file.close()

Why is this, and how can I make the output function iterate (like it does with print)?

like image 575
user1569317 Avatar asked Aug 01 '12 20:08

user1569317


3 Answers

Your issue is that you can only return once from a function:

def test():
    return 1
    return 2

x = test()
# x is now 1

You'll want to either use yield or return a tuple of values:

def this_will_work():
    yield 1
    yield 2

x = list(this_will_work()) # See below for why we are using list
# x is now [1, 2]

def so_will_this:
    return 1, 2

x = so_will_this()
# x is now (1, 2)

Using yield turns your function into a generator that can be iterated over - if you are only interested in all the final values you can use list to turn the generator into a list of all the values your generator yields. Alternately you can loop over it using for ... in.

like image 100
Sean Vieira Avatar answered Sep 21 '22 07:09

Sean Vieira


In the version you're using to write the file, the function returns (via the first return statement) after the first iteration of the while loop. Based on what you have you might want something like this:

def writecode (q, a, b, c):
    results = []
    while b < q:
        b = b + 1
        results.append("v%d_%d_%d = pairwise (caps[%d],sals[%d],poss[%d],poss[%d],poss[%d],pos_range)" % (a,b,c,a,a,a,b,c))
        results.append("votes%d_%d.append(v%d_%d_%d)" % (b,c,a,b,c,))
        results.append("v%d_%d_%d = pairwise (caps[%d],sals[%d],poss[%d],poss[%d],poss[%d],pos_range)" % (a,c,b,a,a,a,c,b))
        results.append("votes%d_%d.append(v%d_%d_%d)" % (c,b,a,c,b))
        results.append("")
    return "\n".join(results)

x = writecode (5,1,0,4)

out_file = open("code.txt", "a")
out_file.write(x)
out_file.close()

Which works by accumulating each line of output into a list and then returns the single string with all the results joined together with newlines and a trailing newline.

like image 37
martineau Avatar answered Sep 20 '22 07:09

martineau


return immediately exists the function:

return leaves the current function call with the expression list (or None) as return value.

You need to build the string as you go (or, for better performance, create a list of values and join at the end).

like image 21
Hamish Avatar answered Sep 20 '22 07:09

Hamish