Reuse function causes Python dict

I have the following (very simplified) dict. A function get_details

is an API call that I would like to avoid twice.

ret = { 
    'a': a,
    'b': [{
        'c': item.c,
        'e': item.get_details()[0].e,
        'h': [func_h(detail) for detail in item.get_details()],
    } for item in items]
}

      

I could of course rewrite the code like this:

b = []
for item in items:
    details = item.get_details()
    b.append({
        'c': item.c,
        'e': details[0].e,
        'h': [func_h(detail) for detail in details],
    })

ret = { 
    'a': a,
    'b': b
}

      

but would like to use the first approach as it seems more pythonic.

+3


source to share


3 answers


I don't think the second is particularly non-phonic; you have complex initialization and shouldn't rely on going to one simple expression. However, you don't need a temporary list b

; you can work directly with ret['b']

:

ret = { 
    'a': a,
    'b': []
}

for item in items:
    details = item.get_details()
    d = details[0]
    ret['b'].append({
        'c': item.c,
        'e': d.e,
        'h': map(func_h, details)
    })

      



This is also the case where I would opt map

for list comprehension. (If it was Python 3, you would need to wrap this on an additional call list

.)

+3


source


You can use a proxy generator to extract parts from your items. Something like that:



ret = { 
    'a': a,
    'b': [{
        'c': item.c,
        'e': details[0].e,
        'h': [func_h(detail) for detail in details],
    } for (item, details) in ((item, item.get_details()) for item in items)]
}

      

+6


source


I wouldn't try too hard to be more pythonic if that means you are similar to your first approach. I would take your second approach one step further and just use a separate function:

ret = {
    'a': a,
    'b': get_b_from_items(items)
}

      

I think it's as clean as it can be. Use comments / docstrings to indicate that 'b'

, test the function, and then the next person who comes in can quickly read and trust your code. I know you know how to write a function, but for the sake of completeness, here's how I would do it:

# and add this in where you want it
def get_b_from_items(items):
    """Return a list of (your description here)."""
    result = []
    for item in items:
        details = item.get_details()
        result.append({
            'c': item.c,
            'e': details[0].e,
            'h': [func_h(detail) for detail in details],
        })
    return result

      

It's a lot of pythons (note the docstring - very pythonic) and very readable. And of course this has the advantage of being a little more thoroughly validated, abstracting complex logic from higher-level logic and all the other benefits of using functions.

-1


source







All Articles