在Python中,iterable的接口是迭代器接口的子集.这具有的优点是,在许多情况下,它们可以以相同的方式处理.但是,两者之间存在重要的语义差异,因为对于iterable,__iter__返回一个新的迭代器对象而不仅仅是self.我怎样才能测试一个iterable真的是一个可迭代的而不是一个迭代器?从概念上讲,我理解iterables是集合,而迭代器只管理迭代(即跟踪位置)但不是集合本身.
当想要多次循环时,差异是重要的.如果给出了迭代器,则第二个循环将不起作用,因为迭代器已经用完并直接引发StopIteration.
测试一种next方法很有吸引力,但这看起来很危险而且有些不对.我应该检查第二个循环是否为空?
有没有办法以更加pythonic的方式进行这样的测试?我知道这听起来像是针对EAFP的LBYL的经典案例,所以也许我应该放弃?或者我错过了什么?
编辑: S.Lott在下面的回答中说,这主要是想要在迭代器上进行多次传递的问题,并且首先不应该这样做.但是,在我的情况下,数据非常大,并且根据情况必须多次传递以进行数据处理(绝对没有办法解决这个问题).
迭代也由用户提供,并且对于单次传递足够的情况,它将与迭代器一起工作(例如,为了简单起见,由生成器创建).但是,如果用户在需要多次传递时只提供迭代器,那么防止这种情况会很好.
编辑2:
实际上这是一个非常好的抽象基类的例子.将__iter__在迭代器和迭代方法具有相同的名称,但语义上是不同的!所以hasattr没用,但isinstance提供了一个干净的解决方案.
我知道使用java的"foreach"从列表中删除通常是一个很大的禁忌,并且应该使用iterator.remove().但是如果我循环遍历HashMap的keySet(),那么remove()是否安全?像这样:
for(String key : map.keySet()) {
Node n = map.get(key).optimize();
if(n == null) {
map.remove(key);
} else {
map.put(key, n);
}
}
Run Code Online (Sandbox Code Playgroud) 对不起,之前我问了一个关于同一主题的问题,但是我的问题涉及那里描述的另一个方面(如何迭代一个提升...).
看看下面的代码:
#include <iostream>
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/algorithm/string/trim.hpp>
int main(int argc, char** argv) {
using boost::property_tree::ptree;
ptree pt;
read_xml("try.xml", pt);
ptree::const_iterator end = pt.end();
for (ptree::const_iterator it = pt.begin(); it != end; it++)
std::cout << "Here " << it->? << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
好吧,正如我在上面提到的问题中告诉我的那样,有可能property_tree在Boost中使用迭代器,但我不知道它是什么类型,以及我可以使用哪些方法或属性.
好吧,我认为它必须是另一个ptree或代表另一个xml层次结构的东西再次浏览(如果我想),但关于这个的文档是非常糟糕的.我不知道为什么,但在boost docs中我找不到什么好东西,只是关于浏览节点的宏,但这种方法是我真的想避免的.
所以在这里提出我的问题:一旦获得了it的迭代器ptree,我如何访问节点名称,值,参数(xml文件中的节点)?谢谢
我最近遇到了一些奇怪的行为,需要检查一下我的理解.
我在模型中使用了一个简单的过滤器,然后迭代结果.
例如
allbooks = Book.objects.filter(author='A.A. Milne')
for book in allbooks:
do_something(book)
Run Code Online (Sandbox Code Playgroud)
奇怪的是,它只返回了部分书籍清单.
但是,当使用相同的代码并使用iterator()时,这似乎运行良好.
即
for book in allbooks.iterator():
do_something(book)
Run Code Online (Sandbox Code Playgroud)
知道为什么??
ps我确实浏览了django文档,但看不到qeuryset如何在其他任何地方缓存...
iterator()计算QuerySet(通过执行查询)并在结果上返回迭代器.QuerySet通常在内部缓存其结果,以便重复的评估不会导致其他查询;iterator()而是直接读取结果,而不在QuerySet级别进行任何缓存.对于返回大量对象的QuerySet,这通常会带来更好的性能并显着降低内存请注意,
iterator()在已经评估过的QuerySet 上使用将强制它再次进行评估,重复查询.
我想知道,如果有一种方法可以在编译时检查某个迭代器类型的类型T是否为const_iterator.迭代器和const迭代器之间的迭代器定义的类型(value_type,pointer,...)有什么不同吗?
我想实现这样的目标:
typedef std::vector<int> T;
is_const_iterator<T::iterator>::value // is false
is_const_iterator<T::const_iterator>::value // is true
Run Code Online (Sandbox Code Playgroud) §24.1.1/ 3来自C++ 03标准读物,
对于输入迭代器,a == b并不意味着++ a == ++ b.(Equality不保证替换属性或引用透明性.)输入迭代器上的算法绝不应该尝试两次通过相同的迭代器.它们应该是单通道算法.值类型T不需要是可分配类型(23.1).这些算法可以通过istream_iterator类与istreams一起用作输入数据的源.
我无法理解上面引文中的粗体文字.任何人都可以帮我理解这个吗?
另外,以下语句(上述引文中的斜体文字)是什么意思?它是如何与a==b和++a==++b表情?
平等并不保证替代财产或参考透明度.
Run Code Online (Sandbox Code Playgroud)>>from itertools import groupby >>keyfunc = lambda x : x > 500 >>obj = dict(groupby(range(1000), keyfunc)) >>list(obj[True]) [999] >>list(obj[False]) []
范围( x> 500)默认情况下对范围(1000)进行排序.
我期待从0到999的数字按条件(x> 500)分组在dict中.但结果字典只有999.
其他数字在哪里?谁能解释一下这里发生了什么?
我有以下HashMap,其中keya是a String,value并由以下内容表示ArrayList:
HashMap<String, ArrayList<String>> productsMap = AsyncUpload.getFoodMap();
Run Code Online (Sandbox Code Playgroud)
我还在ArrayList<String> foods我的应用程序中实现了另一个.
我的问题是,找出我的第二个HashMap包含特定内容的最佳方法是什么?StringArrayList
我试过没有成功:
Iterator<String> keySetIterator = productsMap.keySet().iterator();
Iterator<ArrayList<String>> valueSetIterator = productsMap.values().iterator();
while(keySetIterator.hasNext() && valueSetIterator.hasNext()){
String key = keySetIterator.next();
if(mArrayList.contains(key)){
System.out.println("Yes! its a " + key);
}
}
Run Code Online (Sandbox Code Playgroud) 这是一段非常简单的代码:
#include <vector>
int main() {
std::vector<int> myVec(5);
std::vector<int>::const_iterator first = myVec.begin();
std::vector<int>::const_iterator last = myVec.begin() + 3;
std::vector<int> newVec1(first, last);
std::vector<int> newVec2(myVec.begin(), last);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
行声明newVec1编译.
行声明newVec2失败,出现以下错误:
prog.cpp: In function 'int main()':
prog.cpp:11:49: error: no matching function for call to 'std::vector<int>::vector(std::vector<int>::iterator, std::vector<int>::const_iterator&)'
std::vector<int> newVec2(myVec.begin(), last);
^
prog.cpp:11:49: note: candidates are:
In file included from /usr/include/c++/4.9/vector:64:0,
from prog.cpp:3:
/usr/include/c++/4.9/bits/stl_vector.h:401:9: note: template<class _InputIterator, class> std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&)
vector(_InputIterator __first, _InputIterator __last,
^
/usr/include/c++/4.9/bits/stl_vector.h:401:9: note: …Run Code Online (Sandbox Code Playgroud) 我从PyCharm收到代码检查警告.我理解逻辑,但我不清楚修复它的适当方法.假设我有以下示例函数:
def get_ydata(xdata):
ydata = xdata ** 2
for i in range(len(ydata)):
print ydata[i]
return ydata
Run Code Online (Sandbox Code Playgroud)
我得到2个警告:
>> Expected type 'Sized', got 'int' instead (at line 3)
>> Class 'int' does not define '__getitem__', so the '[]' operator cannot be used on its instances (at line 4)
Run Code Online (Sandbox Code Playgroud)
该函数的目的当然是解析一个numpy数组的xdata.但PyCharm不知道,所以没有任何进一步的指示假设xdata(因此也是ydata)是一个整数.
解决此警告的适当方法是什么?我应该注意,添加类型检查行将修复警告.这是最佳解决方案吗?例如:
if not type(ydata) is np.ndarray:
ydata = np.array(ydata)
Run Code Online (Sandbox Code Playgroud)
最后,添加Sphinx文档字符串信息似乎对警告没有任何影响.(当xdata指定为str时,警告仍会看到'int').同时迭代y直接导致以下错误:
for y in ydata:
...
>> Expected 'collections.Iterable', got 'int' instead
Run Code Online (Sandbox Code Playgroud)