函数循环通过print输出但不通过return返回。

5

我是一个 Python 新手,使用的是 2.7 版本。

我正在尝试创建一个程序,该程序使用函数生成文本,然后将函数生成的文本输出到文件中。

当在 PowerShell 中仅打印函数时(像这样:http://codepad.org/KftHaO6x),它会按照我想要的方式进行迭代:

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)

尝试将函数输出到文件中时(如此: http://codepad.org/8GJpp9QY),它只给出一个值,即不进行迭代。
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()

这是因为输出函数只能一次性打印所有内容。如果想要迭代输出(和print一样),需要将内容存储在一个列表或生成器中,然后使用循环来逐个输出每个元素。

5
return语句会终止函数的执行(就像大多数(或全部?)编程语言一样):http://docs.python.org/reference/simple_stmts.html#the-return-statement。 - Felix Kling
3
感谢Hamish在问题中提供了实际的代码...... - ldx.a.ldy.c
2
稍微退后一步,你似乎正在使用代码生成。为什么不直接执行代码呢?或者说一些关于你更大的任务的事情? - Francis Avila
我使用代码生成,因为我“需要”大量仅略有不同的代码。引号表示我是一个编程新手,可能完全错误。更大的任务是尝试模拟成对投票。如果您不熟悉这个术语,它基本上意味着计算演员1是否投票给演员2,与演员3相比。因此,如果您有15个演员,您需要计算1,2...n对2 vs. 3、3 vs. 4等的偏好。因此有许多行略有不同的代码。如果您感兴趣,这是我目前的进展:http://codepad.org/Ey5C4Rd7 欢迎提供建议。 - user1569317
我注意到代码中的一个具体问题是,它看起来像你正在保持许多votes#_#列表,可以将其制成单个列表或字典数据结构,通过votes [#] [#]访问。一般而言,当你发现自己需要编写大量几乎相同的代码片段时,询问“这些每个实例的通用情况是什么?”通常很有用。这通常会让您设计一个函数或方法来处理它们,如果提供了正确的数据,则可以通过调用或存储对象属性的参数来处理它们。 - martineau
4个回答

5

你的问题在于一个函数只能有一次return

def test():
    return 1
    return 2

x = test()
# x is now 1

您需要使用yield或返回一个值元组:

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)

使用yield将您的函数转换为一个生成器,可以对其进行迭代 - 如果您只对所有最终值感兴趣,则可以使用list将生成器转换为包含所有生成器生成值的列表。或者,您可以使用for...in循环遍历它。

2

在你写文件的版本中,该函数会在 while 循环的第一次迭代后通过第一个 return 语句返回。根据你的需求,你可能需要像这样的代码:

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()

该函数通过将每行输出积累到列表中,然后使用换行符和尾随换行符将所有结果连接在一起返回单个字符串。


谢谢,您提供的代码完全符合我的需求。非常感谢! - user1569317
@user1569317:不用谢。顺便说一下,可能有更简单的方法来完成你正在做的事情,或者至少让它看起来更易读。我所做的只是向你展示了一个相对简单的方法来实现你已经工作的内容。 - martineau

1

return 立即退出函数:

return 语句将当前函数调用以表达式列表(或 None)作为返回值离开。

您需要在执行过程中构建字符串(或者,为了更好的性能,创建一个值列表并在最后使用 join 连接)。


0
稍作变化;我使用了新式字符串格式化,带有命名字段,应该更容易阅读。
请注意,您正在生成一些重复的块(在每个b==c的情况下,您的输出会出现两次)。
from textwrap import dedent

codeblock = dedent("""\
    v{a}_{b}_{c} = pairwise (caps[{a}],sals[{a}],poss[{a}],poss[{b}],poss[{c}],pos_range)
    votes{b}_{c}.append(v{a}_{b}_{c})
    v{a}_{c}_{b} = pairwise (caps[{a}],sals[{a}],poss[{a}],poss[{c}],poss[{b}],pos_range)
    votes{c}_{b}.append(v{a}_{c}_{b})
""")

def get_code (q, a, b, c):
    return ''.join(codeblock.format(a=a, b=b, c=c) for b in xrange(b, q))

def main():
    with open('code.txt', 'a') as outf:
        outf.write(get_code(5,1,0,4))

if __name__=="__main__":
    main()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接