blueFast
blueFast

Reputation: 44381

Automatically create (and keep) an object when accessed

I would like to do something like this:

class A:
    def hello(): print "Hello"

# I do not want to explicitly setup a:
a = A()

# a = A() -> I want this to happen automatically when I access a
# My first try is this:
def a():
    return A()

# Also, I do not want to call a as a function a(): it must be an object
# And it must stay alive and initialized
a.hello() # a is created, as object of class A
a.hello() # I do not want a second instantiation

How can I implement this? properties? cached-properties? They are only for classes: a is a module-level object.

Upvotes: 1

Views: 89

Answers (3)

georg
georg

Reputation: 214969

def lazyinit(cls):

    class p(object):
        def __init__(self, *args, **kws):
            self._init = lambda: cls(*args, **kws)            
            self._obj  = None

        def __getattr__(self, k):
            if not self._obj:
                self._obj = self._init()
            return getattr(self._obj, k)

    return p

Example:

@lazyinit
class A(object):
    def __init__(self, a, b):
        print("initializing...")
        self.x = a + b + 2

    def foo(self):
        return self.x

x = A(39, 1)
print x
print x.foo()
print x.foo()

Upvotes: 1

blueFast
blueFast

Reputation: 44381

Generalization of the answer by Pavel:

class LazyClass(object):

    def __init__(self, myclass, *args, **kwargs):
        self.instance = None
        self.myclass = myclass
        self.args = args
        self.kwargs = kwargs

    def __getattr__(self, k):
        if self.instance is None:
            self.instance = self.myclass(*self.args, **self.kwargs)

        return getattr(self.instance, k)

class A(object):

    def __init__ (self, name):
        self.name = name
        print "Created"

    def hello(self):
        print "Hello " + self.name

import unittest
class TestLazyClass(unittest.TestCase):

    def setUp(self):
        self.a = LazyClass(A, 'Daniel')

    def test_it(self):
        self.a.hello()
        self.a.hello()

Upvotes: 0

Pavel Anossov
Pavel Anossov

Reputation: 62918

Maybe something like this:

class A(object):
    def hello(self):
        print "Hello"

class LazyA(object):
    def __init__(self):
        self.instance = None

    def __getattr__(self, k):
        if self.instance is None:
            self.instance = A()

        return getattr(self.instance, k)

a = LazyA()

Upvotes: 3

Related Questions