首先,我回顾了quickly.for示例的c++风格迭代器:
//--- Iterating over vector with iterator.
vector<int> v;
. . .
for (vector<int>::iterator it = v.begin(); it!=v.end(); ++it) {
cout << *it << endl;
}
它是灵活的。很容易改变底层的容器类型。例如,您可能会在以后决定插入和删除的数量非常多,以至于列表比向量更有效。它还有许多有用的成员函数。向量的许多成员函数使用迭代器,例如,assign、insert或erase。此外,我们可以双向使用迭代器(如果支持),例如++,--。这对于解析像对象这样的流很有用。
python的问题是:1:目前python for循环语法不如c++ for灵活。2:当iter.end()没有更多的时候,python会抛出异常,而不是"it != next()“风格。这是不灵活的。
问题1:我上面的想法正确吗?
好的。我的问题来了,如何实现一个像c++迭代器一样强大的python迭代器?目前,python for循环语法不如c++ for灵活。我还找到了一些可能的解决方案,比如http://www.velocityreviews.com/forums/t684406-pushback-iterator.html。但它要求用户push_back一个东西,而不是询问迭代器--。
问题2:在python中实现双向迭代器最好的是什么?就像http://www.cplusplus.com/reference/std/iterator/BidirectionalIterator/一样。伪代码如下:
it = v.begin();
while( it!=v.end()) {
//do sth here
if (condition1)
++it;//suppose this iterator supports ++
if(condition2)
--it;//suppose this iterator supports --
}
其主要特点是: 1)双向,2)更简单的“结束”检查。"++“或"--”运算符或公共函数都无关紧要(它们在语义上没有区别)。
谢谢,
更新:我从答案中得到了一些可能的解决方案:
i = 0
while i < len(sequence): # or i < len and some_other_condition
star_it = sequence[i]
if condition_one(star_it):
i += 1
if condition_two(star_it):
i = max(i - 1, 0)
然而,与数组不同,列表的随机访问应该是O(n)。我认为python内部的"list“对象是使用类似链表的东西实现的。因此,这种while循环解决方案效率不高。然而,在c++中,我们有“随机迭代器”,“双向迭代器”。我应该如何获得更好的解决方案?谢谢。
发布于 2012-04-05 21:35:40
对于大多数情况,Python的for
和迭代器是最简单的。这是他们的目标,他们不应该为了灵活性而妥协--他们缺乏灵活性不是问题。
对于不能使用for
循环的少数情况,C++迭代器可能更简单。但是在Python语言中总有一种方法可以做到这一点,这种方法并不比使用C++迭代器复杂。
如果您需要将推进迭代器与循环分开,只需使用while
循环:
it = iter(obj)
try:
while True: # or some secondary break condition other than StopIteration
star_it = next(it)
if condition_one(star_it):
star_it = next(it)
except StopIteration:
pass # exhausted the iterator
我只能想到两种情况,在Python中--it
是有意义的。
第一个是你正在迭代一个序列。在这种情况下,如果需要向后返回,则根本不要使用迭代器--只需使用带有while
循环的计数器:
i = 0
while i < len(sequence): # or i < len and some_other_condition
star_it = sequence[i]
if condition_one(star_it):
i += 1
if condition_two(star_it):
i = max(i - 1, 0)
第二个是如果你在一个双向链表上迭代。在这种情况下,同样,不要使用迭代器--只需正常地遍历节点:
current = node
while current: # or any break condition
if condition_one(current):
current = current.next
if condition_two(star_it):
current = current.prev
在无序集合中,比如set
或dict
,你可以使用它,但是你不能使用上面提到的任何一种方法。然而,在这种情况下,--it
就没有意义了。由于集合在语义上是无序的,因此以前到达的任何项都是合适的--而不仅仅是实际的前一项。
因此,为了知道要返回的正确对象,您需要内存,或者通过迭代mydict.values()
或tuple(myset)
之类的序列并使用计数器,或者通过在执行过程中组装以前的值序列并使用上面的while
循环和next
而不是for
循环。
发布于 2012-04-05 22:09:18
您提到的几种情况的解决方案:
对于键,my_dict.iteritems()中的值: if conditiion( value ):my_dictkey = new_value
对于列表,请使用enumerate()
:
对于索引,item in enumerate(my_list):if condition(item):my_listindex =new_item
def iter_with look_ahead(iterable,sentinel=None):iterable,it_ahead = itertools.tee(iterable) next(it_ahead,None)返回当前的izip_longest(iterable,it_ahead,fillvalue=sentinel),look_ahead in iter_with look_ahead(tokens):#要反向迭代的任何
reversed()
。
my_list = list(my_iterable)
发布于 2012-04-05 21:33:59
实际上,C++迭代器系统并不是很好。迭代器类似于指针,它们有自己的问题:
safely
std::for_each(end, begin, func);
std::for_each(v0.begin(), v2.end(), func);
:
v.end()
cannot be dereferenced safelystd::for_each(end, begin, func);
v.end()
#en2#dereferenced safelystd::for_each(end, begin, func);
Python方法在这方面要好得多(虽然exception的使用一开始可能会让人非常惊讶,但它确实有助于定义嵌套迭代器),因为与其名称相反,Python迭代器更类似于Range
。
Range
的概念比C++11引入的range-for循环结构要好得多:
for (Object& o: range) {
}
使用迭代器可以实现的任何事情都可以通过范围来实现,尽管可能需要一些时间才能意识到这一点,对于我们这些接受过C++类指针迭代器教育的人来说,一些翻译一开始似乎是超现实主义的。例如,子范围可以完美地表示为:
for (Object& o: slice(range, 2, 9)) {
}
其中slice
将接受range
中位置为[2, 9)
的所有元素。
因此,与其与您的语言(Python)作斗争,不如深入研究它并拥抱它的风格。与一种语言作战通常是一场失败的战斗,学习它的习惯用法,变得高效。
https://stackoverflow.com/questions/10028693
复制相似问题