Proxy object for lazy initialization

2.6k Views Asked by At

Are there any ready-to-use Python module that provides an easy to use proxy object that only initializes the "real" object when really needed?

Ideally I'm looking for a transparent implementation so that code dealing with this proxy object does not need to be aware that it is not the actual object.

I want to use it like this:

class Example:
    def __init__(self):
        print("Example initialized")

lazy = Proxy(Example)
print(isinstance(lazy, Example))
# Example initialized
# True

As you can see it would behave very much like a unittest.MagicMock.

If there aren't any libs offering functionality like this out there I'll implement it myself but I want to be sure no one else have done this yet.

EDIT

I expect this proxy object to follow a through implementation like this.

2

There are 2 best solutions below

0
Rodrigo Oliveira On BEST ANSWER

I've found module lazy-object-proxy which does exactly that.

Worth mentioning that as @Marat pointed out Django offers a solution as well, though I do not want to import Django just for that, if you're already using it in your project it will be a perfectly fine solution.

0
Magnus Lind Oxlund On

There's Werkzeug's LocalProxy:

# external_module.py
from werkzeug.local import LocalProxy

_internal = None

def init_value():
    global _internal
    _internal = "I'm ready now!"

proxy = LocalProxy(lambda: _internal)
# main.py
from external_module import _internal, proxy, init_value

print(_internal)   # None
print(proxy)       # None
init_value()
print(proxy)       # I'm ready now!
print(_internal)   # None

The lazy-loading aspect isn't covered in the documentation, but LocalProxy does what you're asking for, namely:

  1. Acts as a proxy for another object
  2. Defers evaluation until the object is accessed (as opposed to at import, for instance)
  3. Presents itself as the proxied object (from the documentation):

"__repr__ and __class__ are proxied, so repr(x) and isinstance(x, cls) will look like the proxied object. Use issubclass(type(x), LocalProxy) to check if an object is a proxy."

from werkzeug.local import LocalProxy

class Example:
    def __init__(self):
        print("Example initialized")

lazy = LocalProxy(Example)              # Example initialized
print(isinstance(lazy, Example))        # True