如何以与列表或字典无关的方式迭代对象?

时间:2016-01-24 03:52:51

标签: python python-3.x dictionary

作为我尝试编写的一些代码的一部分,我试图在使用之前验证一些用户输入。我想做类似于以下操作的内容,无论集合是列表还是字典,都可以完全相同,最好不必总是将其转换为两者之一。

list_or_dict = {0:7, 1:12}  # or [7, 12]
for addr, value in list_or_dict.items():
    if addr > addr_max:
        raise Exception()
    if value > val_max:
        raise Exception()

编辑:

为了清楚起见,我只期望字典的整数键。此外,如果仅出于一致性原因,我希望列表的标记是一个地址。

5 个答案:

答案 0 :(得分:1)

假设它是dict并尝试将其转换为list。如果失败,那么您已经有list

list_or_dict = {0:7, 1:12}  # or [7, 12]
try:
    list_or_dict = list(list_or_dict.items())
except AttributeError:
    list_or_dict = list(enumerate(list_or_dict))
# your processing

请注意,如果字典版本始终具有从0开始的整数键并且每个项目增加1,则这将仅产生正确的结果。否则,您将不得不找到填写这些缺失数据的其他方法。另请注意,如果确实是一致的模式,则可以只检查对象的长度,而不是检查每个键或索引。您也可以使用any()来简化此问题(()之后您不需要Exception):

list_or_dict = {0:7, 1:12}  # or [7, 12]
try:
    list_or_dict = list(list_or_dict.values())
except AttributeError:
    pass
if len(list_or_dict) >= addr_max or any(value > val_max for value in list_or_dict):
    raise Exception

答案 1 :(得分:1)

我会使用enumerate(list_or_dict)list_or_dict.items(),具体取决于它是什么。然后在两种情况下都有(addr, value)对,并且可以使用相同的代码。

>>> def check(list_or_dict):
        items = enumerate(list_or_dict) if isinstance(list_or_dict, list) else list_or_dict.items()
        for addr, value in items:
            print(addr, value)

>>> check({0:7, 1:12})
(0, 7)
(1, 12)
>>> check([7, 12])
(0, 7)
(1, 12)

答案 2 :(得分:1)

这是一种只有一个循环的方法。它使用单个迭代器,提供连续的(addr, value)对。如果参数是列表,则addr始终为Nonevalue为连续列表元素;如果参数是dict,(addr, value)是dict的项目。我假设列表的元素类似于dicts的值;如果它们与键类似,则进行相应调整。

def handle_list_or_dict(ld):
    if isinstance(ld, list):
        ld_iter = ((None, value) for value in ld)
    else:
        ld_iter = ld.items()

    for addr, value in ld_iter:
        if addr is not None and addr > addr_max:
            raise Exception()
        if value > val_max:
            raise Exception()
        # Do what you really want to do... Here we just print:
        print(addr, value)

拿它旋转:

>>> addr_max = 2; val_max = 12
>>> handle_list_or_dict({0:7, 1:12})
0 7
0 12

>>> handle_list_or_dict([7, 12])
None 7
None 12

异常认识:

>>> addr_max = 0
>>> handle_list_or_dict([7, 12])    # won't raise
None 7
None 12

>>> handle_list_or_dict({0:7, 1:12})  # will raise
Traceback (most recent call last):
...
Exception

将上限更改为addr_max = 2; val_max = 10,列表和dicts都会提升超出范围的值。

答案 3 :(得分:0)

您可以通过检查类型来单独处理列表和词典。这是一个例子:

x-vendor-feature

答案 4 :(得分:0)

您可以在循环开头使用if 运算符来获取预期的迭代器:

def agnostic(x):
    for y in x if isinstance(x,list) else x.items():
        print(y)

例如,

>>> x = [1,2,3]
>>> agnostic(x)
1
2
3
>>> d = {0:1,2:7}
>>> agnostic(d)
(0, 1)
(2, 7)

请注意,您可以在不可知迭代器的定义中用x.items()x.keys()替换x.values(),具体取决于字典的确切部分(如果是这样)你想要迭代。