任何可迭代对象的值(而不是键)的通用迭代器
Posted
技术标签:
【中文标题】任何可迭代对象的值(而不是键)的通用迭代器【英文标题】:Generic iterator over the values (instead of over the keys) of any iterable 【发布时间】:2011-05-05 20:43:02 【问题描述】:是否有一种通用的方法来获取一个迭代器,该迭代器总是迭代字典或其他可迭代对象(列表、集合...)的值(最好,尽管它也可以迭代键)?
让我详细说明一下:当你执行“iter(list)
”时,你会得到一个迭代器值(不是索引,这听起来很像字典中的“键”)但是当你执行“iter(dict)
”时,你拿到钥匙。
是否有一条指令、属性……不管……它总是迭代可迭代对象的值(或键),无论它是什么类型的可迭代对象?
我有一个带有“附加”方法的代码,它需要接受几种不同类型的可迭代类型,而我能想出的唯一解决方案是这样的:
#!/usr/bin/python2.4
class Sample(object):
def __init__(self):
self._myListOfStuff = list()
def addThings(self, thingsToAdd):
myIterator = None
if (isinstance(thingsToAdd, list) or
isinstance(thingsToAdd, set) or
isinstance(thingsToAdd, tuple)):
myIterator = iter(thingsToAdd)
elif isinstance(thingsToAdd, dict):
myIterator = thingsToAdd.itervalues()
if myIterator:
for element in myIterator:
self._myListOfStuff.append(element)
if __name__ == '__main__':
sample = Sample()
myList = list([1,2])
mySet = set([3,4])
myTuple = tuple([5,6])
myDict = dict(
a= 7,
b= 8
)
sample.addThings(myList)
sample.addThings(mySet)
sample.addThings(myTuple)
sample.addThings(myDict)
print sample._myListOfStuff
#Outputs [1, 2, 3, 4, 5, 6, 7, 8]
我不知道...它看起来有点...对我来说很笨重
能够为这样的情况获得一个通用的迭代器真是太好了,所以我可以写一些类似的东西......
def addThings(self, thingsToAdd):
for element in iter(thingsToAdd):
self._myListOfStuff.append(element)
...如果迭代器总是给出值,或者...
def addThings(self, thingsToAdd):
for element in iter(thingsToAdd):
self._myListOfStuff.append(thingsToAdd[element])
...如果迭代器返回键(我知道集合中 key 的概念有点“特殊”,这就是为什么我更喜欢迭代值但仍然...也许它可以返回存储值的哈希值)。
Python中有这样的东西吗? (顺便说一句,我得用Python2.4)
提前谢谢大家
【问题讨论】:
“我不知道......它看起来有点......对我来说很笨重” 对。由于您将字典(不是序列)视为序列,因此您正在创建自己的问题。 @S.Lott > 但是集合呢?它们被认为是序列吗? (根据docs.python.org/library/… 似乎并非如此)我可以像处理列表一样迭代集合。对我来说(让我们承认,我对 Python 的了解并不多)集合听起来更像字典而不是列表(不是位置顺序,并且用于存储值的集合的散列听起来非常类似于字典中的“键” )。也许我弄错了,但对我来说,集合很像带有“自动”生成键(哈希)的字典。 是的,集合不是序列(它不保持顺序)。但这也不是映射。这是一个非常简单的collection,它只强调成员身份,仅此而已。尽管碰巧使用了哈希,比如字典(在引入之后不久,它们就有了自己的数据结构,而不是像你暗示的那样从字典派生),但它们在概念上是非常不同的。集合不说“键”和“值”。它们不是映射。 @BorrajaX:“但是集合呢?”由于您将字典和集合(不是序列)视为序列,因此您正在创建自己的问题。 [我认为没有必要列举所有您视为序列的非序列。] 它们都是不同的。您不能将它们视为相似。时期。如果你试图强迫它们相似,结果必须很笨拙。你想达到什么目的?所有这些笨拙代码背后的真正目的是什么? @S.Lott > 多亏了 delnan 和 Laurence Gonsalves 的回答,我明白了其中的区别。 “所有这些笨拙代码背后的真正目的是什么?” -> 我认为我的问题和其中的代码已经清楚地说明了这一点。当然这只是一个简化的例子,但有时我会在字典中接收数据,有时在列表中。我只是想知道为字典/列表创建迭代器的最佳方法。 【参考方案1】:大多数集合没有概念或“键”或“值”。他们只是存储项目,并且迭代它们会为您提供这些项目。只有映射(dict-likes)提供“键”和“值”。迭代它们的默认方式使用键,因为for x in collection: assert x in collection
应该是一个不变量(与key in d
相比,(key, value) in d
很少有意义)。所以没有办法只迭代值,因为最少的集合有称为“值”的东西。
但是,您可以选择忽略映射中的键。由于您必须使用 Python 2.4,因此使用 ABC 是不可能的……我担心最简单的方法是:
def iter_values(it):
if hasattr(it, 'itervalues'):
return it.itervalues()
return iter(x)
它仍然可以中断,但可以处理 dicts 和类似的映射。
【讨论】:
太棒了。并感谢您对“为什么”这样做的额外解释! :-) @BorrajaX:我主要只是总结了 AM 对***.com/questions/3744568/…的回答 哦...在我发表评论后 12 分钟有更多奖励回复...令人惊讶!再次感谢你!编程明智,我想我就像一个小孩......总是问“为什么?,为什么?,为什么?”这种回复对我来说很棒:-) FWIW:在旧版本的 Python 中,字典不可迭代,也不支持in
运算符。添加这两种功能的决定并非完全没有争议,因为使这些拖曳操作使用键而不是值会导致与列表和元组不一致(正如问题所暗示的那样)。【参考方案2】:
我不知道有什么内置的东西可以做到这一点。我想你可以这样做:
def itervalues(x):
if hasattr(x, 'itervalues'): return x.itervalues()
if hasattr(x, 'values'): return iter(x.values())
return iter(x)
【讨论】:
【参考方案3】:您正在寻找的是 dict.items()
方法,它返回 (key, value) 元组。
这是一个使用示例:
d = 'a': 1, 'b': 2, 'c': 3
for k, v in d.items():
print "key:", k, "- value:", v
正如你想象的那样,会输出
key: a - value: 1
key: b - value: 2
key: c - value: 3
编辑:如果你想得到一个真正的迭代器而不仅仅是一个序列,你也可以使用dict.iteritems()
方法,它的工作原理是一样的。
Edit2: 似乎我误解了你的问题,因为你似乎要求一个通用函数可以与任何迭代一起使用,忘记我的答案;-)
【讨论】:
没关系!感谢您花费的时间,它很好地解释了 iteritems() 的工作原理。谢谢!以上是关于任何可迭代对象的值(而不是键)的通用迭代器的主要内容,如果未能解决你的问题,请参考以下文章