Python—为什么我的列表没有在这个方法的范围之外被修改?我如何修改我的代码,使它是正确的?

Python—为什么我的列表没有在这个方法的范围之外被修改?我如何修改我的代码,使它是正确的?,python,list,filter,scope,Python,List,Filter,Scope,我有以下方法: def instances(candidate, candidates): count = candidates.count(candidate) # Removing candidate from candidates. # list(filter(candidate.__ne__, candidates)) return {candidate: count} 其目的是查找列表中某个元素的实例数,从列表中删除这些实例,并返回表示该元素及其实例

我有以下方法:

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]
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
但是,对于最后一行,我得到的是:

>>> print(someList)
[1, 1, 1, 2, 3]
列表(filter(candidate.\ne\uu,candidates))
返回我想要的正确列表,但它似乎只存在于函数的作用域中。如果我修改这一行,改为读取
candidates=list(filter(candidate.\uu______,candidates))
,由于某种原因,
candidates
被解释为函数范围内的局部变量。我不能简单地返回列表过滤器,因为我需要为程序的另一部分返回
Key:Value

我发现非常奇怪的是,
candidates
在这一行被解释为局部变量,而就在它上面,
candidates
的引用被解释为函数的参数

有人能帮我理解为什么会这样吗?如果可能,建议与预期目的一致的解决方案?谢谢


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

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
至于为什么它不起作用的解释,你可以找到一个详细的解释,我会自己尝试一下:

Python是“按值传递”,当您讨论传递
int
str
时,这是非常直接的。这就是说,当你传递“一个对象”时,它会变得更加混乱——你实际上传递的是对该对象引用的副本

这意味着对对象本身的任何更改都将在函数外部可见-,但是如果尝试更改引用本身-,它将不可见。还记得“复制”部分吗?您没有传递引用,但传递了该引用的副本-因此,将值重新分配给该引用副本将不可见


注释:另一个(好)选项是“更改指针后面的对象”-如他的回答中所示,使用切片

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

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
至于为什么它不起作用的解释,你可以找到一个详细的解释,我会自己尝试一下:

Python是“按值传递”,当您讨论传递
int
str
时,这是非常直接的。这就是说,当你传递“一个对象”时,它会变得更加混乱——你实际上传递的是对该对象引用的副本

这意味着对对象本身的任何更改都将在函数外部可见-,但是如果尝试更改引用本身-,它将不可见。还记得“复制”部分吗?您没有传递引用,但传递了该引用的副本-因此,将值重新分配给该引用副本将不可见

注释:另一个(好)选项是“更改指针后面的对象”-如他的回答中所示,使用切片

过滤器(候选者。候选者)
不修改
候选者
。它返回新的迭代器。并且
list(过滤器(…)
返回新列表

试试这个

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

# Removing candidate from candidates.
for i in range(count)
    candidates.remove(candidate)
return {candidate: count}
过滤器(候选者.\uu___,候选者)
不修改
候选者
。它返回新的迭代器。并且
list(过滤器(…)
返回新列表

试试这个

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

# Removing candidate from candidates.
for i in range(count)
    candidates.remove(candidate)
return {candidate: count}
在这行中,候选变量被解释为局部变量,而在它上面,对候选变量的引用被解释为函数的参数,这真的很奇怪

蟒蛇。它有变量
foo=bar
表示“使变量
foo
指向
bar
指向的任何位置”。重新指定变量只需重新定位指针。它不允许您更改指向给定值的“其他”变量。使用相同的方法传递参数:创建指向对象的新指针。因此,没有直接的支持

就地修改列表是通过切片语法完成的。你可以这样做:

candidates[:] = filter(candidate.__ne__, candidates)
在这行中,候选变量被解释为局部变量,而在它上面,对候选变量的引用被解释为函数的参数,这真的很奇怪

蟒蛇。它有变量
foo=bar
表示“使变量
foo
指向
bar
指向的任何位置”。重新指定变量只需重新定位指针。它不允许您更改指向给定值的“其他”变量。使用相同的方法传递参数:创建指向对象的新指针。因此,没有直接的支持

就地修改列表是通过切片语法完成的。你可以这样做:

candidates[:] = filter(candidate.__ne__, candidates)
list(filter(candidate.\uu ne\uuu,candidates))
(特别是
filter
)不修改列表
候选者
,它只返回一个与
候选者
不同的新筛选列表

就你而言,我建议如下:

>>> someList = [1, 1, 1, 2, 3]
>>> print(instances(1, someList))
{1: 3}
>>> print(someList)
[2, 3]
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
list(filter(candidate.\uu ne\uuu,candidates))
(特别是
filter
)不修改列表
候选者
,它只返回一个与
候选者
不同的新筛选列表

就你而言,我建议如下:

>>> someList = [1, 1, 1, 2, 3]
>>> print(instances(1, someList))
{1: 3}
>>> print(someList)
[2, 3]
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

在这种情况下,您甚至不需要
list()
;切片作业需要任何时间。@kindall:谢谢,修复了。谢谢!第一个链接的url特别有用。在这种情况下,您甚至不需要
list()
;切片分配将需要任何时间。@kindall:谢谢,fix