任何可迭代对象的值(而不是键)的通用迭代器

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() 的工作原理。谢谢!

以上是关于任何可迭代对象的值(而不是键)的通用迭代器的主要内容,如果未能解决你的问题,请参考以下文章

搞清楚 Python 的迭代器可迭代对象生成器

迭代器可迭代对象迭代器对象生成器生成器表达式和相关的面试题

可迭代对象迭代器与生成器

迭代器可迭代对象与生成器

Python全栈开发之---迭代器可迭代对象生成器

可迭代对象,迭代器(对象),生成器(对象)