带有bug的双重前置函数

时间:2014-01-06 03:13:09

标签: python

这是一个我坚持的功课问题:

你的同学声称编写了一个函数,用一个前两个值替换列表中的每个值(第一个值为0)。例如,如果列表[1,3,7,11]作为参数传递,则该函数应返回[0,2,6,14] - 注意:22不是输出的一部分。这是代码:

def double_preceding(values): 
    if (values != []): 
        temp = values[0] 
    values[0] = 0
    for i in range(1, len(values)): 
        values[i] = 2 * temp 
        temp = values[i]

分析此功能并重写它以使其按预期工作。

我甚至无法遵循代码所做的事情,有人可以向我解释

2 个答案:

答案 0 :(得分:0)

以下是对给定代码的解释,以及我在其中看到的错误:

def double_preceding(values): 
    if (values != []):    # this if checks for an empty list, to avoid exceptions
        temp = values[0] 
    values[0] = 0  # but this line is not indented, so you may get an IndexError anyway
    for i in range(1, len(values)): # this loops over all indexes but the first (0)
        values[i] = 2 * temp  # this replaces the current value with double temp
        temp = values[i] # this line however saves the same doubled value as the new temp

因此,我看到的两个错误是对空列表的错误处理,以及赋值代码中的逻辑错误,该错误将导致循环在第一个值之后用列表的原始第一个值乘以2的连续幂来替换值。

解决第二个问题的一个好方法是使用单个语句在循环中完成两个赋值。这是Python可以做的一件很好的事情,许多其他语言都做不到。这是基本版本的样子:

 values[i], temp = temp*2, values[i]

逗号是要注意的关键事项。作业右侧的那个会从tupletemp*2中生成values[i]。左侧的逗号告诉Python解包分配给变量values[i]temp的元组。并按顺序评估这两个部分(首先是右侧的表达式,然后是解包和赋值)。这意味着tempvalues[i]的“旧”值用于构建元组,并且它们都会在以后重新分配并不重要。

如果我们以这种方式进行分配,我们也可以优雅地解决空列表情况。而不是专门处理第一个值并需要检查以确保values[0]是一个有效的表达式,为什么不在开始时将temp设置为0并让循环处理第一个值以及后来的?这是一个完全固定的功能:

def double_preceeding(values):
    temp = 0
    for i in range(len(values)): # loop over all indexes, not skipping the first
        values[i], temp = temp*2, values[i]

如果values为空列表,则循环将不执行任何操作,因为len([])为0且range(0)本身为空。

示例输出:

>>> L=[]
>>> double_preceeding(L)
>>> L
[]
>>> L=[1, 3, 7, 11]
>>> double_preceeding(L)
>>> L
[0, 2, 6, 14]

答案 1 :(得分:-1)

如果我猜错了程序的缩进。见下面的评论:

<强>代码:

def double_preceding(v):
    values = v[:] # Make a copy of the list passed as argument

    if (values != []): # If list is not empty, store the first value in 'temp'
        temp = values[0]
    else:
        return

    v[0] = 0 # Set the first value of the list as '0' (as the problem says it)

    for i in range(1, len(values)): # Iterate 'n - 1' times, where n is the length of the list
        v[i] = 2 * temp # Set the corresponding value to twice the precedent (the precedent is stored in 'temp')
        temp = values[i]

<强>测试

v = [1, 3, 7, 11]
double_preceding(v)
print v

<强>输出:

[0, 2, 6, 14, 22]