0

I am trying to let a class Foo have a @property named bars that behaves like a Python Dictionary where we can access the values in bars using keys and [ ]:

foo = Foo()
foo.bars['hello']

The reason for using the @property decorator is to allow caching of the key values on first access:

class Foo():
    def __init__(self):
        self._bars = {}

    @property
    def bars(self, key):    # <--- looks like this function signature doesnt work
        if key not in self._bars.keys():
            self._bars[key] = hash(key)    # cache computation results on first access
        return self._bars[key]

Unfortunately, the above code leads to the error:

TypeError: bars() missing 1 required positional argument: 'key'

Is it possible to accomplish this using @property?

martineau
  • 119,623
  • 25
  • 170
  • 301
Athena Wisdom
  • 6,101
  • 9
  • 36
  • 60
  • Does this answer your question? [Understanding \_\_getitem\_\_ method](https://stackoverflow.com/questions/43627405/understanding-getitem-method) – Samwise Sep 16 '20 at 17:25
  • @Samwise The solutions in the linked question can help us implement access using `foo['hello']`, but not `foo.bars['hello']`, based on my limited understanding of Python – Athena Wisdom Sep 16 '20 at 17:28
  • Make `bars` an object which implements `__getitem__` with the appropriate caching and then make it a property/attribute of `foo`. – Samwise Sep 16 '20 at 17:33
  • @AthenaWisdom Why not just use a method? – ekhumoro Sep 16 '20 at 17:53
  • @ekhumoro Trying to avoid altering existing code which uses an uncached dictionary by keeping the same syntax when using the cached dictionary. I think Samwise's suggestion works. – Athena Wisdom Sep 16 '20 at 17:57
  • @AthenaWisdom The property decorator is no help at all. You need to create a custom class that implements the required behaviour and assign it to `bar`. – ekhumoro Sep 16 '20 at 18:08
  • @ekhumoro Perfect, thank you – Athena Wisdom Sep 16 '20 at 18:24

0 Answers0