为何两种roll_dice实现结果不同?测试用例返回值不符咨询
问题解析:roll_dice实现差异与测试结果不符的原因
一、为什么预期值是6?
你提到的counted_dice由make_test_dice生成,输出序列为4,1,2,6——这类测试工具的核心逻辑是每次调用骰子函数,按顺序返回序列中的下一个值,且状态持续(不会自动重置)。
你预期roll_dice(1, counted_dice)返回6,本质是假设第一次调用roll_dice(3, counted_dice)会消耗序列的前3个值(4、1、2),剩下的第4个值6会被第二次调用取到。这个预期本身合理,但只有当roll_dice实现会完整执行所有num_rolls次骰子调用时才成立。
二、两种实现的差异导致结果不同的核心原因
1. 列表推导式版本的行为
假设你的列表推导式实现代码如下:
def roll_dice(num_rolls, dice): rolls = [dice() for _ in range(num_rolls)] return 1 if 1 in rolls else sum(rolls)
这个版本的关键特性是:无论是否提前遇到1,都会执行完num_rolls次骰子调用。
当调用roll_dice(3, counted_dice)时:
- 连续调用3次
dice(),依次得到4、1、2,耗尽序列前3个值; - 检测到
rolls包含1,返回1(符合预期); - 此时
counted_dice的下一次调用会返回剩余的6。
因此后续调用roll_dice(1, counted_dice)时,会得到6,和你的预期一致。
2. while循环版本的行为
假设你的while循环实现代码如下:
def roll_dice(num_rolls, dice): total = 0 remaining = num_rolls while remaining > 0: current = dice() if current == 1: return 1 total += current remaining -= 1 return total
这个版本的关键特性是:一旦掷出1,立即返回结果,终止后续所有骰子调用。
当调用roll_dice(3, counted_dice)时:
- 第一次调用
dice()得到4,非1,累加后剩余次数变为2; - 第二次调用
dice()得到1,立即返回1(符合预期),但没有执行第三次骰子调用; - 此时
counted_dice的下一次调用会返回序列中未被消耗的第三个值2。
因此后续调用roll_dice(1, counted_dice)时,会得到2,这就是你看到的不符合预期的结果。
三、结论
两种实现的核心差异在于是否会完整执行所有指定次数的骰子调用:
- 列表推导式版本会耗尽所有
num_rolls次调用,哪怕中途遇到1; - while循环版本会在遇到1时提前终止,剩余次数的骰子调用不会执行。
而你预期的6,是建立在“第一次调用消耗了3次骰子”的假设上,只有列表推导式版本符合这个假设,while循环版本则因为提前终止,只消耗了2次骰子,导致后续调用取到了未被消耗的2而非6。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

