1

I would like to know whether there is a more efficient way of replacing a particular value in a dictionary. By "more efficient" I mean to avoid looking up the same key twice. I don't expect it would make a big difference, but I find myself doing the following alot:

foo = {'a': 0, 'b': 1}
foo['b'] = bar(foo['b'])

Update

I think the assignment above is "looking up the same key twice" because the following prints "Hashing b" three times.

class LoudKey:
    def __init__(self, key):
        self.key = key
    def __hash__(self):
        print(f'Hashing {self.key}')
        return self.key.__hash__()

b = LoudKey('b')
foo = {'a': 0, b: 1}
# first "Hashing b"
foo[b] = float(foo[b])
# next two "Hashing b"s

If dict.__getitem__ and dict.__setitem__ are really not duplicating effort somehow, an elaboration on that would also be accepted as an answer.

Ian
  • 1,062
  • 1
  • 9
  • 21
  • Can you provide an example of `bar`? – zenofpython Apr 05 '22 at 22:31
  • @zenofpython How about `float`? – Ian Apr 05 '22 at 22:32
  • 2
    As it happens, you aren't actually doing two kep lookups at all. The first `foo['b']` calls the `__setitem__` method, and the second `foo['bar']` calls the `__getitem__`. So it's not inefficient. Of course, if you are doing this recursively, you'd have to provide a larger example for anything to be simplified. – zenofpython Apr 05 '22 at 22:36
  • 2
    Food for thought: [Python dictionary "plus-equal" behavior](https://stackoverflow.com/questions/22569981/python-dictionary-plus-equal-behavior) – wwii Apr 05 '22 at 22:39
  • @zenofpython Trying to understand ... see update. – Ian Apr 05 '22 at 23:11

1 Answers1

0

You can do it by making the dictionary items a mutable type, then mutating it. The simplest is a list with a single element.

>>> b = LoudKey('b')
>>> foo = {'a': [0], b: [1]}
Hashing b
>>> ref = foo[b]
Hashing b
>>> ref[0] = float(ref[0])
>>> foo
{'a': [0], <__main__.LoudKey object at 0x0000000014C66F40>: [1.0]}

You're right that it wouldn't make much difference in practice, though.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622