2

I am new to python so maybe my problem is easy to solve. I have a dictionary organized as follow: my_dict = {'x': (1.1, 3.4), 'y': (4.3, 7.5), 'z': (7.3, 9.5)}. I would like to reduce each value by the same number, so this is what I am trying to do:

for k,v in my_dict.items():
    for a, b in v:
        a = a * 0.3
        b = b * 0.3 
        my_dict[k] = (a, b)
return my_dict

When using this code, I receive this error:

for a, b in v:
TypeError: 'float' object is not iterable

So it seems that the "for a, b in v" loop is trying to iterate through float, which is not possible. Thus, I tried to print my_dict.items() and k,v in the for loop, in order to see what is the for loop iterate through, and this is what I get:

for k,v in my_dict.items():
    print my_dict.items()
    print k,v

[('x', (1.1, 3.4)), ('y', (4.3, 7.5)), ('z', (7.3, 9.5))]
y (4.3, 7.5)

I can see two wierd things: - I was expecting the "print k,v" command to print each key, values couple, but I am getting only the y key with its value - By looking at the my_dict.items(), it seems to me that v is not a float, but a tuple containing two float. So why do I get the float object is not iterable error?

Any help is well appreciated. Again, I am sorry if this is a silly question, but I just started using python and I am stuck with this.

Thank you!

1
  • 2
    You simply meant a, b = v to unpack the tuple Commented Apr 2, 2020 at 17:46

7 Answers 7

2

You could use a dict comprehension here

>>> {k: tuple(i * 0.3 for i in v) for k, v in my_dict.items()}
{'x': (0.33, 1.02), 'y': (1.2899999999999998, 2.25), 'z': (2.19, 2.85)}
Sign up to request clarification or add additional context in comments.

3 Comments

This sound great! Thanks! What if I want to make a * 0.3 and b * 0.5?
In that case, use (v[0]*0.3, v[1]*0.5).
You could also do it with something more general, such as (i * c for i, c in zip(v, (0.3, 0.5)) for k, v ...)
1

@CoryKramer already nailed the Pythonic way to do this. To focus on your code ...

Your inner "loop" isn't the right technique. You do not need to iterate through the tuple -- that takes one element at a time, and you want two at once. Rather, you need to "unpack" the tuple.

my_dict = {'x': (1.1, 3.4), 'y': (4.3, 7.5), 'z': (7.3, 9.5)}

for k,v in my_dict.items():
    print("dict:", k, v)
    a, b = v
    print("val:", a, b)
    a = a * 0.3
    b = b * 0.3
    my_dict[k] = (a, b)

2 Comments

you can use for k, (a, b) in my_dict.items(): and save one line of code)
I know -- I'm doing my best to keep close to OP's code.
1

The line of code for a, b in v doesn't make sense because there is only one value v which is your tuple. You are already looping through the items in the dictionary in your outer loop. Try the following:

for k,v in my_dict.items():
    a, b = v
    a = a * 0.3
    b = b * 0.3 
    my_dict[k] = (a, b)
return my_dict

Comments

1

you can unpack your dict values:

for k, (a, b) in my_dict.items():
    a *= 0.3
    b *= 0.3 
    my_dict[k] = (a, b)

or you can use:

dict(map(lambda x: (x[0], (x[1][0]*0.3, x[1][1]*0.3)),   my_dict.items()))

Comments

1

You don't have to iterate over the tuple but just assign it to variables:

for k,v in my_dict.items():
    a, b = v
    a = a * 0.3
    b = b * 0.3 
    my_dict[k] = (a, b)
return my_dict

and a bit nicer solution:

for k,v in my_dict.items():
    my_dict[k] = tuple([0.3*x for x in v])
return my_dict

Comments

1

The problem here, is that by doing:

for a, b in v

You are trying to iterate over a single tuple, which does not really make sense since you're already unpacking it.

Note that all you'd need is to unpack its values as:

k,v = next(iter(my_dict.items()))
a, b = v

Now a and b contains both tuple values respectively. So the only issue in your code is that inner for.

So it is clear that it does not make sense, but why does the error occur?

This is because Python is expecting v to be an iterable of iterables, since you're trying to unpack each iterable into k and v. In this case, when you iterate over v, the first item to be returned is its first float, which cannot be unpacked.

Note that if we instead iterated over a list containing the tuple, your approach would work:

for k,v in my_dict.items():
    for a, b in [v]:
        a = a * 0.3
        b = b * 0.3 
        my_dict[k] = (a, b)

Though, as mentioned it does not make sense, given that you can just directly unpack them:

for k,v in my_dict.items():
    a, b = v
    a = a * 0.3
    b = b * 0.3 
    my_dict[k] = (a, b)

Comments

1

I would suggest using a dictionary comprehension:

my_dict = {'x': (1.1, 3.4), 'y': (4.3, 7.5), 'z': (7.3, 9.5)}

f = 0.3
my_dict = {k:(a*f,b*f) for k,(a,b) in my_dict.items()}

print(my_dict)  # {'x': (0.33, 1.02), 'y': (1.2899999999999998, 2.25), 'z': (2.19, 2.85)}

If you want to keep the loop, you will have to remove the nested for-loop because it is not needed to expand the tuples. You can simply write it like this:

for k,(a,b) in my_dict.items():
    my_dict[k] = (a*0.3, b*0.3)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.