我有以下方法:
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
的引用被解释为函数的一个参数。
有人可以帮我理解为什么会这样吗?如果可能的话,建议一个符合预期目的的解决方案?谢谢!
答案 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是“按值传递”,当您讨论传递int
或str
时,这非常简单。也就是说,当你传递“一个对象”时,它会变得更加混乱 - 你实际传递的是对该对象的副本。
这意味着对象本身的任何更改都将在函数外部显示 - 但如果您尝试更改引用本身 - 它将不可见。还记得“复制”部分吗?你做了不传递引用但是该引用的副本 - 所以重新为引用的副本分配值将不可见!
评论:另一个(好)选项是“更改指针后面的对象” - 正如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