2

I'd like to accept either one dict or a list of dicts as a function argument. So far, I've come up with the following, but I suspect I've missed something completely obvious, and am using something fragile (isinstance):

def wrap(f):
    def enc(inp):
        if isinstance(inp, list):
            for item in inp:
                f(item)
        else:
            f(inp)
    return enc

@wrap
def prt(arg):
    # do something with the dict
    print arg.keys()
urschrei
  • 25,123
  • 12
  • 43
  • 84
  • 2
    Don't just think in lists. A sequence of dicts could also be passed as a tuple, a set, or even a generator expression, and the same code in your function could safely iterate over any of them. – PaulMcG Sep 04 '11 at 15:39

2 Answers2

3

I would accept a variable number of arguments:

def wrap(f):
    def enc(*args):
        for item in args:
            f(item)
    return enc

Then you can either pass a single dictionary, multiple dictionaries or a list by unpacking it.

See Arbitrary Argument Lists in the Python tutorial.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    There no point accepting `kwargs` if you're going to drop them on the floor. – Ned Batchelder Sep 04 '11 at 14:58
  • @Ned: True, I guess it was habit... removed. – Felix Kling Sep 04 '11 at 15:00
  • @urschrei: Why? `enc` is looping over all arguments, so each `item` is a dictionary and is passed to `f`. – Felix Kling Sep 04 '11 at 15:02
  • @felix-kling When I use your version of `wrap` in python 2.7 it prints the dict or the list of dicts, whichever I pass. It doesn't seem to actually be unpacking the list. See here: https://gist.github.com/1193001 – urschrei Sep 04 '11 at 15:12
  • 1
    @urschrei You are passing in you dictionaries as a list in your gist example. *args creates the list for you, so just `prt({foo:"foo"},{bar:"bar"})` will do the trick. – Mark Gemmill Sep 04 '11 at 15:38
  • @urschrei: *You* have to unpack the list. Have a look at the link in my answer. The call should be: `prt(*[{'b': 'bar'}, {'c': 'baz'}])`. Or pass the dictionary as normal arguments, as @Mark showed. – Felix Kling Sep 04 '11 at 15:39
  • @felix kling Argh, *that's* what I was missing. Thanks! – urschrei Sep 04 '11 at 15:48
2

I would avoid using a decorator, I think it would be easier to handle the logic for that in your ptr function:

def prt(arg):
    try:
        # we'll try to use the dict...
        print arg.keys()
    except AttributeError:
        # ok that didn't work, we have a list of dicts
        for d in arg:
            print d.keys()
Zach Kelling
  • 52,505
  • 13
  • 109
  • 108