1

I have few classes that get initiated from my database tables. I am avoiding querying the database if I already have done it before by weak referencing it with it's id in a WeakValueDictionary like so:

import weakref, gc

class anobject():

    cache = weakref.WeakValueDictionary()

    def __init__(self, id):

        #query database for id
        #Initiate instance with data from db

        self.id = id
        self.objectText = f'Object with id {self.id}'
        anobject.cache[self.id] = self

    def __new__(cls, id):
        if id in cls.cache.keys():
            return cls.cache[id]
        else:
            return object.__new__(cls)

    def __str__(self):
        return self.objectText

def main():
    ob1 = anobject(0)
    ob2 = anobject(1)

    ob3 = anobject(0)

    print(ob1, ob2, ob3)
    print(anobject.cache[0])

    del ob1
    gc.collect()

    print(anobject.cache[0])

if __name__ == "__main__":
    main()

Output:

Object with id 0 Object with id 1 Object with id 0
Object with id 0
Object with id 0

I don't worry about objects being out of date since data won't change in database during the life of the object.

Is there a better, more pythonic way to achieving this? Since in the future I also need to initiate objects by parameters other than just id.

kokoi
  • 35
  • 1
  • 6
  • As long as you're aware that `__init__` will be executed even for instances that were taken from your cache, I don't see anything wrong with this. – Aran-Fey Nov 24 '19 at 18:03
  • Suggest you follow PEP 8 naming conventions and name your class `AnObject`. – martineau Nov 24 '19 at 18:08
  • @Aran-Fey, I acutally was not aware of that. Thank's for pointing it out. I have to figure a way to keep track of that in the __init__ function as well. – kokoi Nov 24 '19 at 18:20
  • This is similar to a singleton, and those are usually implemented with metaclasses for this exact reason. Take a look at [this question](https://stackoverflow.com/q/6760685/1222951). – Aran-Fey Nov 24 '19 at 18:25

0 Answers0