lazy-object-proxy

repository·master·Indexed 42 days ago

https://github.com/ionelmc/python-lazy-object-proxy

A fast and thorough lazy object proxy for Python that defers the execution of a factory function until the proxy object is actually used. It provides the `lazy_object_proxy.Proxy` class to wrap expensive computations, supporting comprehensive delegation of attribute access, magic methods, context managers, and async operations. It includes a `__resolved__` property to check if the underlying object has been instantiated.

Tokens
2.3K
Snippets
10
Records
15
Agent score
53%

What's inside lazy-object-proxy

  1. What is lazy-object-proxy and when to use it

    master

    Concept

    lazy-object-proxy is a fast and thorough lazy object proxy. It is designed for scenarios where the target object is only available or needed much later in the execution flow.

    Comparison with wrapt.ObjectProxy

    While both are proxies, they serve different primary purposes:

    • Use lazy-object-proxy when you want to wrap a function that produces an object, and you want that function to be called only upon the first use of the proxy.
    • Use wrapt.ObjectProxy when you want to override specific methods (via subclassing) and forward all other calls to an existing target object.
  2. Install lazy-object-proxy

    master

    You can install the stable version of lazy-object-proxy from PyPI using pip. If you need the latest in-development version, you can install it directly from the GitHub master branch.

    # Install stable version
    pip install lazy-object-proxy
    
    # Install in-development version
    pip install https://github.com/ionelmc/python-lazy-object-proxy/archive/master.zip
  3. Set up python-lazy-object-proxy for local development

    master

    To develop locally, fork the repository, clone your fork, and create a new branch. Use tox to run all checks and the documentation builder.

    # 1. Clone your fork
    git clone git@github.com:YOURGITHUBNAME/python-lazy-object-proxy.git
    
    # 2. Create a branch
    git checkout -b name-of-your-bugfix-or-feature
    
    # 3. Run all checks and docs builder
    tox
    
    # 4. Commit and push
    git add .
    git commit -m "Your detailed description of your changes."
    git push origin name-of-your-bugfix-or-feature
  4. Proxy delegation behavior

    master

    The Proxy class implements comprehensive delegation to the wrapped object:

    • Attribute Access: __getattr__ and __setattr__ delegate to the wrapped object.
    • Magic Methods: Supports arithmetic (__add__, __sub__, etc.), comparison (__eq__, __lt__, etc.), container operations (__len__, __getitem__, __contains__), and more.
    • Context Managers: Supports __enter__ and __exit__.
    • Async Support: Supports __await__, __aenter__, __aexit__, __aiter__, and __anext__ if the environment supports it.
    • Metadata: Properties like __module__, __doc__, and __name__ are proxied to match the wrapped object.
  5. Understand the Proxy lifecycle and internals

    master

    The Proxy class manages the lifecycle of the wrapped object through several internal mechanisms:

    1. __factory__: The callback function used to create the target object.
    2. __target__: The storage for the materialized object once the factory has been executed.
    3. __resolved__: A boolean flag that is True if __target__ is set, and False otherwise.
    4. __wrapped__: The primary interface to the underlying object. When accessed, it checks if __target__ exists. If not, it calls __factory__, stores the result in __target__, and returns it.
  6. Use lazy_object_proxy.Proxy to defer expensive computations

    master

    The lazy_object_proxy.Proxy class creates a proxy object that wraps a function. The function is only executed the first time the proxy object is actually accessed or used. Subsequent accesses return the cached result of the function without re-executing it.

    import lazy_object_proxy
    
    def expensive_func():
        from time import sleep
        print('starting calculation')
        # just as example for a very slow computation
        sleep(2)
        print('finished calculation')
        # return the result of the calculation
        return 10
    
    obj = lazy_object_proxy.Proxy(expensive_func)
    # function is called only when object is actually used
    print(obj)  # now expensive_func is called
    
    print(obj)  # the result without calling the expensive_func