Elegantly handle different parameter types

I have a function that, in the simplest of cases, operates on an iterable of items.

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

Sometimes, I do not want to pass it an iterable of items directly, but rather an object that provides a method to get the iterable:

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

I can merge these two cases like this:

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

This works just fine. Now I get a third use case that looks like this:

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

I can still use the try-except approach, since the interfaces are incompatible. However, the nested try catch would start to become very ugly. More so when I want to add a fourth use-case. Is there any way to solve this without nesting the try -blocks?


As it stands, you should probably use at least two methods here,the third just calling the first with the itertools.chain.from_iterable result. You could also potentially have a use for *args; it depends on your precise case (providing a real example is helpful). You can also use a simple helper function to return the right type of iterator.

Perhaps this might work out:

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):

Must agree with Chris: the magic understand-everything input is going to turn around and bite you. If you pass it an iterable of objects-with-iterables of iterables, how do you specify at what level to actually start processing data?

Far better to stick with "either a list or a generator" as input, then pre-process your calls to the function.


To check if an object is iterable:

import collections
isinstance(obj, collections.Iterable)

This should get you rid of some problems.

Also, a way to handle such problems is by using recursivity (don't know if it's applicable though):

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

上一篇: 刷新会话时,SQL语句的Nhibernate顺序

下一篇: 优雅地处理不同的参数类型