user3121900
user3121900

Reputation: 111

Retrieve properties of a class instance stored in a dictonary

After reading this wonderful article about speeding-up looping in Python by using built-in iterators and implicit loops I have tried it in my code. It worked well on many parts, but one small part still annoys me - the values I iterate over are sometimes stored as fields of a class which are the dictionary values, and I can't get rid of looping over my dictionary to retrieve them.

Here is a simplified version of my code:

class Pair:
    def __init__(self):
        self.radius = 0.0

indices = [(x, y) for y in range(5) for x in range(5)]
d = {}
for (x, y) in indices:
    d[x, y] = Pair()
    d[x, y].radius = (x ** 2 + y ** 2) ** 0.5

sub_list = [(1, 2), (2, 3), (3, 4)]

values = [d[ind].radius for ind in sub_list] # <-- main problem

print reduce(lambda x, y: x + y, values)

So the dictionary d have tuples (x, y) as keys and Pair instances as values, and my goal is to sum the radii of the given sub_list of pairs (sub_list could be the entire dictionary). Is there any "broadcasting" technique for that, or the loop in the marked line is inevitable?

BTW - I am a beginner, so any useful comment about the code (including styling and Pythonish will be appreciated.

Thanks!

Upvotes: 2

Views: 55

Answers (1)

zmo
zmo

Reputation: 24812

well your code is not so bad, though there's one useless thing, which is your object Pair. You may just as well store the radius as value in the dict:

indices = [(x, y) for y in range(5) for x in range(5)]
sub_list = [(1, 2), (2, 3), (3, 4)]

d = {}

for (x, y) in indices:
    d[x, y] = (x ** 2 + y ** 2) ** 0.5

values = [d[ind] for ind in sub_list] # <-- no problem

print reduce(lambda x, y: x + y, values)

I can't get rid of looping over my dictionary to retrieve them.

Reread your code! You're not looping over the dictionary, you're iterating over the sub_list! Maybe this is a syntax problem, here's how you could rewrite that iteration:

values=[]
for ind in sub_list:
    values.append(d[x, y])

And think about it, what you want is to get the precalculated radius value for each element of the sublist. So there's actually no other way than iterating over the sublist! Whether you do it using a list comprehension or a map is mostly a matter of personal preference, even though the list comprehension is more efficient:

>>> timeit.repeat(lambda: [d[ind] for ind in sub_list])
[0.8207108974456787, 0.8075330257415771, 0.788733959197998]
>>> timeit.repeat(lambda: map(lambda ind: d[ind], sub_list))
[1.6066839694976807, 1.630357027053833, 1.755575180053711]

If you talk about complexity, consider the size of d being m, and the one of values being n, then:

values = [d[ind] for ind in sub_list]

is O(n)!

Upvotes: 1

Related Questions