在Python中,iterable的接口是迭代器接口的子集.这具有的优点是,在许多情况下,它们可以以相同的方式处理.但是,两者之间存在重要的语义差异,因为对于iterable,__iter__返回一个新的迭代器对象而不仅仅是self.我怎样才能测试一个iterable真的是一个可迭代的而不是一个迭代器?从概念上讲,我理解iterables是集合,而迭代器只管理迭代(即跟踪位置)但不是集合本身.
当想要多次循环时,差异是重要的.如果给出了迭代器,则第二个循环将不起作用,因为迭代器已经用完并直接引发StopIteration.
测试一种next方法很有吸引力,但这看起来很危险而且有些不对.我应该检查第二个循环是否为空?
有没有办法以更加pythonic的方式进行这样的测试?我知道这听起来像是针对EAFP的LBYL的经典案例,所以也许我应该放弃?或者我错过了什么?
编辑: S.Lott在下面的回答中说,这主要是想要在迭代器上进行多次传递的问题,并且首先不应该这样做.但是,在我的情况下,数据非常大,并且根据情况必须多次传递以进行数据处理(绝对没有办法解决这个问题).
迭代也由用户提供,并且对于单次传递足够的情况,它将与迭代器一起工作(例如,为了简单起见,由生成器创建).但是,如果用户在需要多次传递时只提供迭代器,那么防止这种情况会很好.
编辑2:
实际上这是一个非常好的抽象基类的例子.将__iter__在迭代器和迭代方法具有相同的名称,但语义上是不同的!所以hasattr没用,但isinstance提供了一个干净的解决方案.
我想做以下事情:
我想声明迭代字典的类的实例变量.
我们假设我有这个哈希值
hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
Run Code Online (Sandbox Code Playgroud)
我希望将每个键作为类的实例变量.我想知道我是否可以声明迭代遍历该哈希的变量.像这样的东西:
class MyClass
def initialize()
hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
hash.each do |k,v|
@k = v
end
end
end
Run Code Online (Sandbox Code Playgroud)
我知道这不起作用!我只是把这段代码放在一边看看你能不能理解我想要的更清楚.
谢谢!
我知道使用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) 之前有一些关于这个问题的问题; 我的理解是,调用std::vector::erase只会使处于擦除元素之后的位置的迭代器无效.但是,在擦除元素之后,该位置的迭代器是否仍然有效(当然,前提是它end()在擦除后没有指向)?
我对如何实现向量的理解似乎表明迭代器肯定是可用的,但我不完全确定它是否会导致未定义的行为.
作为我正在谈论的一个例子,下面的代码从向量中删除所有奇数整数.此代码是否会导致未定义的行为?
typedef std::vector<int> vectype;
vectype vec;
for (int i = 0; i < 100; ++i) vec.push_back(i);
vectype::iterator it = vec.begin();
while (it != vec.end()) {
if (*it % 2 == 1) vec.erase(it);
else ++it;
}
Run Code Online (Sandbox Code Playgroud)
代码在我的机器上正常运行,但这并不能说服它是有效的.
所有讨论都是关于python 3.1.2; 请参阅Python文档以获取我的问题的来源.
我知道什么zip呢; 我只是不明白为什么它可以像这样实现:
def zip(*iterables):
# zip('ABCD', 'xy') --> Ax By
iterables = map(iter, iterables)
while iterables:
yield tuple(map(next, iterables))
Run Code Online (Sandbox Code Playgroud)
比方说我打电话zip(c1, c2, c3).如果我理解正确,iterables最初是元组(c1,c2,c3).
该行将其iterables = map(iter, iterables)转换为迭代器,如果迭代,它将返回iter(c1),iter(c2),iter(c3).
在循环中,map(next, iterables)是会返回一个迭代器next(iter(c1)),next(iter(c2))以及next(iter(c3))如果通过迭代.的tuple通话将其转换为(next(iter(c1)), next(iter(c2)), next(iter(c3)),用尽其参数(iterables据我可以告诉在第一个调用).我不明白while循环如何继续,因为它检查iterables; 如果它继续,为什么tuple调用不返回空元组(迭代器耗尽).
我确定我错过了很简单的东西..
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)