1

I have a class with class variables that should be lazily created. I have a working version for instance variables. How do you implement one for class variables? The following is an example usage.

print(MyDatabase.users) # first call should load the users variable and return value
print(MyDatabase.users) # second call should return the stored value

The first error I got when I tried is AttributeError: type object 'MyDatabase' has no attribute 'users' . Is there a way to catch the error in the class?

ferk86
  • 2,325
  • 1
  • 23
  • 27
  • 4
    Use `@properties` with a custom getter – rdas Sep 07 '22 at 15:12
  • Can you go into more detail? Another way I realized is to name the class with _. So I have `MyDatabase = _MyDatabase()` and then the usage will be same like `MyDatabase.users`. The strategy might be easier to maintain than ways using class variable. – ferk86 Sep 07 '22 at 15:29
  • https://stackoverflow.com/a/5191224/1394353 any help? Search for “python class property”, this stuff shows up from time to time. But generally putting *data* on a class, rather than say maybe only-once initialization stuff (compute an expensive url for an attribute lookup that is rarely needed) tends to have worked out, for me, as a code smell later on. A singleton may be an alternative. – JL Peyret Sep 07 '22 at 16:06

1 Answers1

1

Use @property like so:

class MyDatabase:

    def __init__(self):
        self._users = None

    @property
    def users(self):
        if self._users is None:
            # load users
            print('users loaded')
            self._users = ['u']
        return self._users


db = MyDatabase()

print(db.users)  # first call should load the users variable and return value
print(db.users)  # second call should return the stored value

The loading happens only the first time:

users loaded
['u']
['u']
rdas
  • 20,604
  • 6
  • 33
  • 46