优雅地处理不同的参数类型

时间:2010-12-14 20:59:27

标签: python

我有一个函数,在最简单的情况下,它可以在一个可迭代的项目上运行。

def foo(items):
    for item in items:
        # do stuff

有时候,我不想直接传递一个可迭代的项目,而是一个提供获取可迭代项的方法的对象:

def foo(obj):
    for item in obj.iteritems():
        # do same stuff as above

我可以合并这两个案例:

def foo(obj):
    try:
        items = obj.iteritems()
    except ValueError:
        items = obj
    for item in items:
        # do stuff

这很好用。现在我得到第三个用例,如下所示:

def foo(objs):
    for item in itertools.chain.from_iterable(obj.iteritems() for obj in objs):
        # do same stuff again

我仍然可以使用try-except方法,因为接口不兼容。但是,嵌套的try catch会变得非常难看。当我想添加第四个用例时更是如此。有没有办法解决这个问题而不嵌套try - 块?

4 个答案:

答案 0 :(得分:2)

按照目前的情况,你应该在这里使用至少两种方法,第三种只用itertools.chain.from_iterable结果调用第一种方法。你也可以使用* args;这取决于你的确切情况(提供一个真实的例子是有帮助的)。您还可以使用简单的辅助函数来返回正确类型的迭代器。

也许这可能会成功:

def _foo_iter(obj):
    try:
        return obj.iteritems()
    except AttributeError:
        return obj

def foo(*objs):
    for obj in objs:
        for item in _foo_iter(obj):

答案 1 :(得分:1)

必须同意克里斯:神奇的理解 - 一切输入都会转过来咬你。如果你传递一个可迭代的迭代对象的可迭代对象,你如何指定实际开始处理数据的级别?

最好坚持使用“列表或生成器”作为输入,然后预处理对函数的调用。

答案 2 :(得分:0)

检查对象是否可迭代:

import collections
isinstance(obj, collections.Iterable)

这可以让你摆脱一些问题。

此外,处理此类问题的一种方法是使用递归(不知道它是否适用):

def foo(obj):
    if isinstance(obj, collections.Iterable):
        for el in obj:
            foo(el)
    # now do stuff

答案 3 :(得分:0)

hasattr(object, name)

    if hasattr(obj, '__iter__'):
        return [o for o in obj]
    elif hasattr(obj, 'iteritems'):
        return [o for o in obj.iteritems()]
    elif isinstance(obj, list) or isinstance(obj, tuple):
        return [o.iteritems() for o in [o for o in obj]]
    else:
        raise TypeError

class Bar(list):
    def iteritems(self):
        return self.__iter__()

print foo([1,2,3])
print foo(Bar([1,2,3]))
print foo([[1,2,3], [1,2,3]])
print foo(1)

[1, 2, 3]
[1, 2, 3]
[[1, 2, 3], [1, 2, 3]]
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    print foo(1)
  File "test.py", line 11, in foo
    raise TypeError
TypeError