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

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

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 -blocks?


就目前而言,您应该至少使用两个方法,第三个方法是使用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):

必须同意克里斯:魔术的理解 - 所有的投入都会转而咬你。 如果你通过一个迭代器来迭代对象 - 迭代器的迭代器,那么你如何指定在什么级别上真正开始处理数据?

更好地坚持使用“列表或发生器”作为输入,然后预处理您的呼叫到该功能。


要检查一个对象是否可迭代:

import collections
isinstance(obj, collections.Iterable)

这应该让你摆脱一些问题。

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

def foo(obj):
    if isinstance(obj, collections.Iterable):
        for el in obj:
            foo(el)
    # now do stuff
链接地址: http://www.djcxy.com/p/3981.html

上一篇: Elegantly handle different parameter types

下一篇: Do a mass db.delete on App Engine, without eating CPU