函数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']
请解释为什么这些产生不同的产出。
答案 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[:]