在python中遇到列表问题

时间:2015-07-10 20:18:47

标签: python list python-2.7

函数satisfiesF()将字符串列表L作为参数。 function f接受一个字符串作为参数返回true或false。函数satisfiesF()修改L只包含那些f(s)返回true的字符串。 我有两个不同的程序旨在产生相同的输出。但我得到了不同的产出。

第一个程序:

def f(s):
    return 'a' in s

def satisfiesF(L):
    k=[]
    for i in L:
        if f(i)==True:
            k.append(i)
    L=k
    print L
    print
    return len(L)


L = ['a', 'b', 'a']
print satisfiesF(L)
print L

输出:

['a','a']

2

['a','b','a']

第二个程序:

def f(s):
    return 'a' in s


def satisfiesF(L):
    for i in L:
        if f(i)==False:
            L.remove(i)

    print L
    print
    return len(L)

L = ['a', 'b', 'a']
print satisfiesF(L)
print L

输出:

['a','a']

2

['a','a']

请解释为什么这些产生不同的产出。

5 个答案:

答案 0 :(得分:2)

在第二个函数中,您将2视为函数外L的长度和所有元素,因为您正在设置一个局部变量L,它是{k的引用1}},在函数外部创建的L不受影响。要查看L中的更改,您需要使用L[:] = k,然后在更改原始列表对象时L将在函数外部提供['a', 'a'] L传入函数的列表。

首先,您要直接修改L,以便在功能之外的L中看到更改。

如果你做的话,也永远不要遍历要删除元素的列表 L = ['a', 'b', 'a','a','d','e','a'],您将获得您所期望的行为。复制for i in L[:]或使用反向for i in reversed(L):

答案 1 :(得分:1)

在第一个函数中,您在L中分配satisfiesF(),但您永远不会修改原始列表。当您编写L=k时,会使引用L引用与k相同的列表。它不会分配给原始列表。

相反,在第二个功能中,您修改L而不重新分配它。

另外,作为旁注,您不应在迭代时修改列表。

作为第二方注释,您可以将satisfiesF重写为一行:

L = [item for item in L if f(item)]

答案 2 :(得分:1)

这被错误地投了票。问题改变了。所以,答案已经过时了。以下是更改问题的答案:

L=k

上述意味着我们失去了对L的引用。

所以,试试这个:
对于第一个程序,请注释上面的作业,如下所示,以保留对L:

的引用
# L=k
del L[:]
L[:] = k

现在两个程序都会输出相同的,低于一个:

['a', 'a']

2
['a', 'a']

祝你好运。

答案 3 :(得分:1)

在问题中,有两个Ls。全球性的和本地的。该     print L 语句打印GLOBAL L,你没有在程序中变异。

因此,为了让程序知道你要改变全局L而不是本地L,你可以添加该行     globals()['L'] = L 到你的第一个节目。我希望这可以帮助你!

答案 4 :(得分:0)

在第一个程序中,如果要改变原始列表L并查看函数所做的更改,则应将代码中的L = K替换为L[:] = k

def satisfiesF(L):
    k=[]
    for i in L:
        if f(i)==True:
            k.append(i)

    # new code --------
    L[:] = k   # before: L = K
    # -----------------

    print L
    print
    return len(L)

这将为您提供[' a',' a']以外的功能。

关于在第二个程序中改变循环内的列表...... 只是要记住在" for"循环,python使用内部计数器跟踪它在列表中的位置,该计数器在每次迭代结束时递增。

当计数器的值达到列表的当前长度时,循环终止。这意味着如果您在循环中改变列表,则可能会产生令人惊讶的后果。

例如,请查看下面的for循环:

my_list = ['a', 'b', 'c', 'd']

>>>print "my_list - before loop: ", my_list
my_list - before loop:  ['a', 'b', 'c', 'd']


for char in my_list:
    if char == 'a' or char == 'b':
        my_list.remove(char)

>>>print "my_list - after loop: ", my_list    
my_list - after loop:  ['b', 'c', 'd']

这里,隐藏的计数器从索引0开始,发现" a" (在my_list [0]中)在列表中,并删除它,将my_list的长度减少到3(从最初的4开始)。然后计数器增加到1,代码继续检查"如果"条件,在位置my_list [1],在变异列表中(现在为len == 3)。这意味着你将跳过" b"字符(现在在索引0处出现),即使必须将其删除。

对此的一个解决方案是使用切片来克隆并创建一个新列表,您可以从中删除项目:

cloneList = my_list[:]