Python - 为什么我的列表没有在此方法范围之外被修改?如何修改我的代码?

时间:2015-06-01 02:24:43

标签: python list filter scope

我有以下方法:

def instances(candidate, candidates):
    count = candidates.count(candidate)

    # Removing candidate from candidates. #
    list(filter(candidate.__ne__, candidates))
    return {candidate: count}

其预期目的是查找列表中某个元素的实例数,从列表中删除这些实例,并返回表示该元素及其实例数的Key:Value对。

因此,如果我创建一个列表并调用该函数,它应该执行以下操作:

>>> someList = [1, 1, 1, 2, 3]
>>> print(instances(1, someList))
{1: 3}
>>> print(someList)
[2, 3]

然而,对于最后一行,我得到了这个:

>>> print(someList)
[1, 1, 1, 2, 3]

list(filter(candidate.__ne__, candidates))返回我想要的正确列表,但它似乎只存在于函数的范围内。如果我修改此行而不是读取candidates = list(filter(candidate.__ne__, candidates)),由于某种原因,candidates被解释为函数范围内的局部变量。我无法简单地返回列表过滤器,因为我需要将Key:Value对返回给我的程序的另一部分。

我觉得奇怪的是candidates被解释为这一行中的一个局部变量,而在它上面,对candidates的引用被解释为函数的一个参数。

  

有人可以帮我理解为什么会这样吗?如果可能的话,建议一个符合预期目的的解决方案?谢谢!

4 个答案:

答案 0 :(得分:4)

  

我觉得很奇怪,候选词被解释为这一行中的局部变量,而在它之上,候选词的引用被解释为函数的一个参数。

Python doesn't have references。它有变量。 foo = bar表示“将变量foo指向任何bar点。”重新分配变量只是重新定位指针。它不允许您更改指向给定值的“其他”变量。使用相同的方法传递参数:创建一个指向该对象的新指针。因此,没有对three star programming

的直接支持

使用切片语法完成就地修改列表。你可以这样做:

candidates[:] = filter(candidate.__ne__, candidates)

答案 1 :(得分:0)

您可以修改函数以返回两个结果:

def instances(candidate, candidates):
    count = candidates.count(candidate)    
    return {candidate: count}, list(filter(candidate.__ne__, candidates))

当你运行它时,请使用:

someList = [1, 1, 1, 2, 3]
res, someList = instances(1, someList)
print res

至于为什么它不起作用的解释 - 你可以找到一个详细的here,我会尝试自己试一试:

Python是“按值传递”,当您讨论传递intstr时,这非常简单。也就是说,当你传递“一个对象”时,它会变得更加混乱 - 你实际传递的是对该对象的副本。

这意味着对象本身的任何更改都将在函数外部显示 - 如果您尝试更改引用本身 - 它将不可见。还记得“复制”部分吗?你做了传递引用但是该引用的副本 - 所以重新为引用的副本分配值将不可见!

评论:另一个(好)选项是“更改指针后面的对象” - 正如Kevin在答案中使用切片显示!

答案 2 :(得分:0)

filter(candidate.__ne__, candidates)不会修改candidates。它返回新的迭代器。 list(filter(...))会返回新列表。

试试这个

def instances(candidate, candidates):
count = candidates.count(candidate)

# Removing candidate from candidates.
for i in range(count)
    candidates.remove(candidate)
return {candidate: count}

答案 3 :(得分:0)

list(filter(candidate.__ne__, candidates))(具体为filter)并未修改列表candidates,它只返回一个新的过滤的列表,该列表与candidates

在您的情况下,我建议如下:

while True:
    try:
        candidates.remove(candidate)
    except ValueError:  
        # If there's no more candidate in candidates
        # ValueError will be raised, in this case, we can stop removing
        break