最近很多小伙伴都在问Pythonfor循环和迭代器行为和python迭代器和for循环区别这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展foreach循环和迭代器模式是类似的吗?
最近很多小伙伴都在问Python for循环和迭代器行为和python迭代器和for循环区别这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展foreach 循环和迭代器模式是类似的吗?二者有什么区别?、for循环和迭代器Iterator、Java中增强的for循环和迭代器的优点是什么?、JAVA使用增强for循环和迭代器遍历Map集合等相关知识,下面开始了哦!
本文目录一览:- Python for循环和迭代器行为(python迭代器和for循环区别)
- foreach 循环和迭代器模式是类似的吗?二者有什么区别?
- for循环和迭代器Iterator
- Java中增强的for循环和迭代器的优点是什么?
- JAVA使用增强for循环和迭代器遍历Map集合
Python for循环和迭代器行为(python迭代器和for循环区别)
我想了解更多有关的信息iterators
,所以如果我错了,请纠正我。
迭代器是一个对象,该对象具有指向下一个对象的指针,并作为缓冲区或流(即,链表)读取。它们特别有效,因为它们所做的只是通过引用而不是使用索引来告诉您下一步是什么。
但是我仍然不明白为什么会发生以下行为:
In [1]: iter = (i for i in range(5))In [2]: for _ in iter: ....: print _ ....: 01234In [3]: for _ in iter: ....: print _ ....:In [4]:
经过迭代器(In [2]
)的第一个循环后,就好像它已被消耗并且留空,因此第二个循环(In [3]
)不输出任何内容。
但是,我从未为iter
变量分配新值。
for
循环幕后到底发生了什么?
答案1
小编典典您的怀疑是正确的:迭代器已被消耗。
实际上,您的迭代器是一个generator,这是一个对象,它 只能
被迭代 一次。
type((i for i in range(5))) # says it''s type generatordef another_generator(): yield 1 # the yield expression makes it a generator, not a functiontype(another_generator()) # also a generator
它们高效的原因与“参考”告诉您下一步是什么无关。它们之所以有效,是因为它们仅根据请求生成下一个项目。所有项目都不是一次生成的。实际上,您可以拥有一个无限生成器:
def my_gen(): while True: yield 1 # again: yield means it is a generator, not a functionfor _ in my_gen(): print(_) # hit ctl+c to stop this infinite loop!
其他一些更正可以帮助您增进理解:
- 生成器不是指针,并且不像您可能在其他语言中所熟悉的那样表现为指针。
- 与其他语言的区别之一:如上所述,生成器的每个结果都是即时生成的。除非请求,否则不会产生下一个结果。
- 关键字组合
for
in
接受一个可迭代的对象作为其第二个参数。 - 在您的示例示例中,可迭代对象可以是生成器,但也可以是任何其他可迭代对象,例如
list
,或dict
,或str
对象(字符串)或提供所需功能的用户定义类型。 - 该
iter
函数将应用于对象以获取迭代器(顺便说一句:iter
正如您所做的那样,不要在Python中用作变量名-它是关键字之一)。实际上,更准确地说,是调用对象的__iter__
方法(在大多数情况下,所有iter
函数都可以执行;这__iter__
是Python所谓的“魔术方法”之一)。 - 如果调用
__iter__
成功,则next()
循环将函数一次又一次地应用于可迭代对象,并将提供给的第一个变量for
in
分配给next()
函数的结果。(请记住:可迭代对象可以是生成器,也可以是容器对象的迭代器,或任何其他可迭代对象。)实际上,更准确地说:它调用了迭代器对象的__next__
方法,这是另一个“魔术方法”。 - 在
for
当循环结束next()
引发StopIteration
异常(当可迭代不具有另一个目的是产生时通常发生next()
被调用)。
您可以通过for
这种方式“手动”在python中实现循环(可能并不完美,但足够接近):
try: temp = iterable.__iter__()except AttributeError(): raise TypeError("''{}'' object is not iterable".format(type(iterable).__name__))else: while True: try: _ = temp.__next__() except StopIteration: break except AttributeError: raise TypeError("iter() returned non-iterator of type ''{}''".format(type(temp).__name__)) # this is the "body" of the for loop continue
上面的代码与您的示例代码几乎没有区别。
实际上,for
循环中最有趣的部分不是for
,而是in
。单独使用in
会产生与产生不同的效果for
in
,但是,了解in
使用其参数的作用非常有用,因为它for
in
实现了非常相似的行为。
单独使用时,
in
关键字首先调用对象的__contains__
method,这是另一个“魔术方法”(请注意,使用时将跳过此步骤for
in
)。使用in
一个容器本身,你可以做这样的事情:1 in [1, 2, 3] # True
‘He’ in ‘Hello’ # True
3 in range(10) # True
‘eH’ in ‘Hello’[::-1] # True如果可迭代对象不是容器(即它没有
__contains__
方法),则in
下一步尝试调用该对象的__iter__
方法。如前所述:该__iter__
方法返回Python中称为iterator的值。基本上,迭代器是一个对象,您可以next()
在1上使用内置的泛型函数。生成器只是迭代器的一种类型。如果
__iter__
成功调用,则in
关键字将函数next()
一次又一次地应用于可迭代对象。(请记住:可迭代对象可以是生成器,也可以是容器对象的迭代器,或任何其他可迭代对象。)实际上,更确切地说,它调用迭代器对象的__next__
方法。- 如果对象没有
__iter__
返回迭代器的方法,in
则使用对象的__getitem__
方法2退回到旧式迭代协议。 - 如果上述所有尝试均失败,您将获得一个
TypeError
异常。
如果您希望创建自己的对象类型以进行迭代(即,您可以使用,也可以for
in
仅in
在其上使用),那么了解生成器中yield
使用的关键字(如上所述)很有用。
class MyIterable(): def __iter__(self): yield 1m = MyIterable()for _ in m: print(_) # 11 in m # True
将yield
函数或方法变成生成器而不是常规函数/方法的存在。__next__
如果使用生成器(它会__next__
自动提供),则不需要该方法。
如果您希望创建自己的容器对象类型(即可以单独使用in
它,但不能使用for
in
),则只需要该__contains__
方法即可。
class MyUselessContainer(): def __contains__(self, obj): return Truem = MyUselessContainer()1 in m # True''Foo'' in m # TrueTypeError in m # TrueNone in m # True
1请注意,要成为迭代器,对象必须实现迭代器协议。这仅意味着__next__
和__iter__
方法都必须 正确
实现(生成器带有“免费”此功能,因此您在使用它们时无需担心)。还要注意,该___next__
方法实际上next
在Python
2中(没有下划线)。
2请参 见此答案以了解创建可迭代类的不同方法。
foreach 循环和迭代器模式是类似的吗?二者有什么区别?
像 php ,C# 这样的语言提供了 foreach 循环来对容器中的每个元素进行迭代处理,是否可以认为这和设计模式中的迭代器循环类似,如果不是的话,二者的主要区别,或者说主要应用场景是什么?for循环和迭代器Iterator
迭代器模式:
把访问逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合的内部结构。
Iterable接口:
foreach遍历集合的优势在于代码更加的简洁,更不容易出错,不用关心下标的起始值和终止值。
从本质上说,foreach其实就是在使用迭代器,在使用foreach遍历时对集合的结构进行修改,和在使用Iterator遍历时对集合结构进行修改本质上是一样的。同样会抛出异常,执行快速失败机制。
在使用Iterator的时候禁止对所遍历的容器进行改变其大小结构的操作。例如,在使用Iterator进行迭代时,如果对集合进行了add/remove操作就会出现ConcurrentModificationException异常。
RandomAccess
what is random and sequential access lists?
java集合类中元素的访问分为随机访问和顺序访问。
随机访问一般是通过index下标访问,行为类似数组的访问。而顺序访问类似于链表的访问,通常为迭代器遍历。
ArrayList是典型的随机访问型,而LinkedList则是顺序访问型。
List接口既定义了下标访问方法,又定义了迭代器方法。因此,其实例既可使用下标随机访问也可以使用迭代器进行遍历,但这两种方式的性能差异很明显。(下标访问比迭代器访问更快)
for循环与迭代器的对比:
1、ArrayList对随机访问比较快,而for循环中使用的get()方法,采用的即是 随机访问的方法,因此在ArrayList里for循环更快(foreach是一个内部循环体,多了其它的逻辑,虽然比for循环慢一些,但还是一个量级的);
2、LinkedList则是顺序访问比较快,Iterator中的next()方法,采用的是 顺序访问方法,因此在LinkedList里只用Iterator更快。
主要还是依据集合的数据结构不同的判断。
ArrayList和LinkedList随机访问的区别
ArrayList是数组结构,随机访问具有常量时间。
LinkedList是链表结构,随机访问分为两步:
1)根据index查找Node,通常是一个for循环查找到index对应的Node
2)返回Node中存储的元素
ArrayList的下标遍历性能高于LinkedList的下标遍历。
Java中增强的for循环和迭代器的优点是什么?
谁能告诉我Java +5中Enhanced for loop和Iterators的优点是什么?
JAVA使用增强for循环和迭代器遍历Map集合
public static void DemoMap(){
Map<String, String> map = new HashMap<String, String>();
// 添加元素
map.put("Mon", "星期一");
map.put("Tues", "星期二");
map.put("Wed", "星期三");
map.put("Thur", "星期四");
map.put("Fir", "星期五");
map.put("Sat", "星期六");
map.put("Sun", "星期日");
// 通过keySet方法获取所有键值
Set<String> keySet = map.keySet();
for (String key : keySet) {
String value = map.get( key);
System.out.println("value:" + value);
}
// 通过entrySet方法获取所有键值
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Entry<String, String> entry : entrySet) {
String entryKey = entry.getKey();
String entryValue = entry.getValue();
System.out.println("entryValue:" + entryValue);
}
Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()){
String key = iterator.next();
System.out.println(key+":"+map.get(key));
}
}
参考链接:http://blog.csdn.net/hello_zhou/article/details/51583526
今天关于Python for循环和迭代器行为和python迭代器和for循环区别的分享就到这里,希望大家有所收获,若想了解更多关于foreach 循环和迭代器模式是类似的吗?二者有什么区别?、for循环和迭代器Iterator、Java中增强的for循环和迭代器的优点是什么?、JAVA使用增强for循环和迭代器遍历Map集合等相关知识,可以在本站进行查询。
本文标签: