[英]why the list behaves differently in python and Java?
我正在学习脚本语言python。 我很了解Java。 我正在尝试将一小段代码从Java转换为python。 但是它们的行为不规律(或者我的理解可能是完全错误的),我在Java中使用以下代码,在其中我将元素无限期地添加到ArrayList中。 所以这会导致内存不足错误,这是我期望的:
import java.util.*;
public class Testing{
public static void main(String[] args){
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(4);
for (int i=0;i<list.size();i++){
list.add(5);
}
}
}
现在在python中翻译了相同的代码:
lst = []
lst.append(5)
lst.append(4)
for i in range(len(lst)):
lst.append(5)
print lst
在这里,我得到的输出: [5, 4, 5, 5]
从我看来,列表是否没有传递为对python中for
循环的引用?
同样在这里
>>> l=[1,2,3]
>>> for i in l[:]:
... l.append(4)
... print l
...
[1, 2, 3, 4]
[1, 2, 3, 4, 4]
[1, 2, 3, 4, 4, 4]
在for
循环内的每次迭代中,我都在增加列表大小,因此迭代应该永远正确吗?
python for
循环评估表达式,该表达式产生仅循环一次的可迭代项。 你可以操纵lst
在循环对象,而不会影响结果for
是循环结束了。 这不同于Java for
构造(这与Python for
语句有很大不同,实际上是Foreach构造),后者为每次迭代评估3个关联表达式。
在第一个示例中,您创建了一个range()
结果,并且一旦创建该结果,就不会为每次循环迭代更新。
在第二个示例中,您使用全长切片( lst[:]
)创建了lst
的副本,以使循环迭代。 不会为每个循环迭代重新创建副本。
但是,这里有一个警告。 for
循环在要迭代的对象上调用iter()
。 对于列表对象,结果列表迭代器的确保留了对原始列表的引用以及迭代索引。 每当for
循环使迭代器前进next()
在其上调用next()
)时,迭代索引就会递增并在原始列表中查找,直到索引等于列表长度为止。 如果您继续添加到循环列表中, 则会创建一个无限循环。
如果您没有创建列表的副本以进行迭代,则可以看到以下内容:
>>> L = [1, 2, 3]
>>> for i in L:
... L.append(4)
... print L
... if len(L) > 30:
... break
...
[1, 2, 3, 4]
[1, 2, 3, 4, 4]
[1, 2, 3, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
[1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
在这里,为L
创建的迭代器随着L
在循环中的扩展而不断产生下一个元素,如果我没有在循环中添加长度限制,那么它将永远持续下去。
range(len(lst))
创建一次范围,然后对其进行迭代,而在java list.size()
则在每次迭代时求值
>列表是否未传递为python中for循环的引用?
所有对象都通过在Python引用传递,并在Python 一切都是对象。 (不是Java基本值,但即使是普通整数和浮点值也是Python中的对象。)
>在for循环内的每次迭代中,我都会增加列表大小,因此迭代应该永远正确吗?
您正在增加l的大小,这是正确的,但是l [:]仅被评估一次,并产生l的浅表副本。 该副本不会在循环中更改,因此在循环内部更改为l不会更改循环变量将采用的值集。
在该循环中将l [:]更改为l,然后您会看到很多输出。
通过将for
循环转换为等效的while
循环,可能最容易解释这一点。
在Java中:
for (int i=0;i<list.size();i++){
list.add(5);
}
int i=0;
while (i<list.size()) {
list.add(5);
++i;
}
在Python伪代码中:
for i in range(len(lst)):
lst.append(5)
_r = range(len(lst))
_i = iter(r)
while _i isn't done:
next(_i)
lst.append(5)
在实践中,您实际上不需要了解iter
*和next
工作的方式,也不需要了解“ _i未完成”部分的工作原理的详细信息**; 关键是for
循环会创建一个迭代器,然后对其进行迭代。 在您的情况下,它将在range
对象上创建一个迭代器(或在Python 2.x中,由range
函数返回的list
)。
但是即使不知道,您仍然可以看到len(lst)
在开始时仅被评估一次,以创建迭代器,而Java list.size()
等效项在每次循环中list.size()
评估。
如果要使用Java样式的for
循环,则必须显式编写while
循环。
* iter
在所有可迭代对象(列表,范围,甚至另一个迭代器)上创建一个迭代器。 迭代器有点像一个智能对象,其中引用了其中的可迭代对象和“当前位置”,尽管在幕后他们很少以这种方式实现。 在迭代器上调用next
有效地返回当前位置的值,并将迭代器前进到下一个迭代器(或等效项,但实际上已实现该迭代器)。
**实际上发生的实际上是一个try:
/ except StopIteration:
,因为在完成的迭代器上调用next
会引发StopIteration
。 当然,它是用C语言实现的(对于其他Python实现,则是Java或.NET或RPython),而C语言实际上使用了一些特殊的魔术代码来循环遍历迭代器,这使其速度更快一些,但几乎没有人需要考虑那部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.