Alex
Alex

Reputation: 33

How can I set dictionary values to behave like instance properties?

I would like to store a number of temperature values as a dictionary instance attribute. Whenever the dictionary key is used, I would like the corresponding value to update, with behaviour similar to that of an instance @property decorator.

Is there a way to to this without updating the entire dictionary? Below is code of how I'd expect it to pan out, with simplified update functions (the real ones will read from sensors), but the temperatures need to update on each access.

import random


class Thermal():

    def __init__(self):
        self.temperatures = {'outside': self.outside, 'inside': self.inside}

    @property
    def outside(self):
        return random.random()

    @property
    def inside(self):
        return 1 + random.random()

    @property
    def c(self):
        return random.random()


a = Thermal()
print(a.temperatures['outside'])
print(a.temperatures['outside'])
print(a.temperatures['inside'])
print(a.temperatures['inside'])

The outside and inside temperatures printed above do not change on access, though of course it works for the basic attribute, c. Is this a case where I need to create a dict subclass, or is there another way to do it? I can resign to having individual instance attributes for each temperature, but I think it's neater in a dictionary and am keen to see if there is a way to achieve this.

Upvotes: 1

Views: 79

Answers (2)

sanyassh
sanyassh

Reputation: 8550

With minimal changes to your code and keeping the semantics like a.temperatures['outside'] here is possible solution:

import random


class Temperatures():  # here
    def __init__(self, thermal):
        self.thermal = thermal

    def __getitem__(self, item):
        return getattr(self.thermal, item)



class Thermal():

    def __init__(self):
        self.temperatures = Temperatures(self)  # and here

    @property
    def outside(self):
        return random.random()

    @property
    def inside(self):
        return 1 + random.random()

    @property
    def c(self):
        return random.random()


a = Thermal()
print(a.temperatures['outside'])
print(a.temperatures['outside'])  # will give different random number
print(a.temperatures['inside'])
print(a.temperatures['inside'])

Upvotes: 2

gmds
gmds

Reputation: 19905

How about this?

class Thermal:

    def __init__(self):
        self._temperatures = {'inside': None, 'outside': None}

    def __getitem__(self, key):
        self.update()
        return self._temperatures[key]

    def update(self):
        # update temperatures here...

Upvotes: 1

Related Questions