Lazy Object Proxy

raw JSON →
1.12.0 verified Tue May 12 auth: no python install: verified quickstart: verified

lazy-object-proxy is a Python library that provides a fast and thorough lazy object proxy implementation. It defers the initialization of an object until its first access, which can be highly beneficial for performance optimization and handling circular dependencies. The library is currently at version 1.12.0 and maintains an active development cycle with regular updates. [5, 10]

pip install lazy-object-proxy
error ModuleNotFoundError: No module named 'lazy_object_proxy'
cause The 'lazy-object-proxy' package is not installed in the Python environment being used, or the virtual environment is not activated. [6, 28]
fix
Run pip install lazy-object-proxy to install the package. If using a virtual environment, ensure it is activated before installation and execution. [3, 6, 28]
error AttributeError: '__proxy__' object has no attribute 'some_attribute'
cause This typically occurs when attempting to access an attribute on the lazy proxy object before the actual underlying object has been initialized, or if the attribute truly does not exist on the proxied object. [2, 22, 23]
fix
Ensure that the proxy has been accessed in a way that triggers its initialization (e.g., calling a method or accessing an attribute that forces the underlying object to load). Verify that the some_attribute exists on the target object that the proxy is meant to represent. [3, 12]
error TypeError: 'Proxy' object is not callable
cause This error arises when you try to call the `lazy_object_proxy.Proxy` instance itself as a function or constructor, instead of calling a method or accessing an attribute of the *proxied* object. [25, 26, 27]
fix
Access the callable method or attribute of the object that the Proxy instance represents, rather than attempting to call the Proxy object directly. For example, if obj = lazy_object_proxy.Proxy(expensive_func), call obj() or obj.method() instead of obj if expensive_func is a callable, or obj.attribute if it's an attribute. [3]
error ValueError: Proxy hasn't been initiated: __factory__ is missing.
cause This internal error indicates that the `lazy_object_proxy.Proxy` instance was created incorrectly or its internal factory function, which is responsible for creating the real object, is somehow missing or inaccessible. [2]
fix
Ensure that the lazy_object_proxy.Proxy is initialized with a valid callable function as its argument, which will be invoked to create the real object upon first access. Example: obj = lazy_object_proxy.Proxy(my_factory_function) where my_factory_function returns the desired object. [3]
breaking Support for older Python versions has been progressively dropped. Version 1.12.0 requires Python >=3.9. Previous versions (e.g., 1.11.0, 1.10.0, 1.8.0, 1.7.1) dropped support for Python 3.8, 3.7, 3.6, and 2.7 respectively. [2, 6, 8]
fix Ensure your project's Python environment meets the minimum requirement of `lazy-object-proxy` (currently >=3.9). Upgrade Python or pin `lazy-object-proxy` to an older compatible version if necessary.
gotcha When `lazy-object-proxy`'s C extension fails to compile (e.g., due to missing build tools or specific environments like PyPy/GraalPy), it gracefully falls back to a pure Python implementation. While functional, this can result in a performance overhead. [11]
fix To maximize performance, ensure a suitable C compiler is available in your environment during installation. On systems where C extensions are intentionally disabled (e.g., PyPy), be aware of the potential for slight performance degradation.
gotcha The `__resolved__` property was added in version 1.6.0. Before this, there was no direct public API to check if the factory function had been called without triggering its execution. [2, 8]
fix For versions 1.6.0 and newer, use `proxy_object.__resolved__` to check if the wrapped object has been resolved. For older versions, direct checking without triggering resolution is not straightforward.
gotcha While `lazy-object-proxy` aims for transparency, deep introspection or specific type comparisons (especially direct `type()` checks) on the proxy object might not always yield the underlying object's type until it's resolved. `isinstance()` typically works as expected due to how proxies handle `__class__` attribute. [3]
fix Prefer `isinstance()` for type checking as it generally works correctly. If you need to access the actual wrapped object's type or properties before resolution, you might need to reconsider if lazy loading is appropriate for that specific use case or trigger resolution explicitly.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.02s 18.1M
3.10 alpine (musl) - - 0.02s 18.1M
3.10 slim (glibc) wheel 1.4s 0.01s 19M
3.10 slim (glibc) - - 0.01s 19M
3.11 alpine (musl) wheel - 0.03s 19.9M
3.11 alpine (musl) - - 0.03s 19.9M
3.11 slim (glibc) wheel 1.6s 0.02s 20M
3.11 slim (glibc) - - 0.02s 20M
3.12 alpine (musl) wheel - 0.03s 11.8M
3.12 alpine (musl) - - 0.04s 11.8M
3.12 slim (glibc) wheel 1.4s 0.04s 12M
3.12 slim (glibc) - - 0.04s 12M
3.13 alpine (musl) wheel - 0.04s 11.5M
3.13 alpine (musl) - - 0.03s 11.4M
3.13 slim (glibc) wheel 1.5s 0.04s 12M
3.13 slim (glibc) - - 0.05s 12M
3.9 alpine (musl) wheel - 0.01s 17.5M
3.9 alpine (musl) - - 0.01s 17.5M
3.9 slim (glibc) wheel 1.9s 0.01s 18M
3.9 slim (glibc) - - 0.01s 18M

This quickstart demonstrates how to create a lazy object proxy. The `expensive_function` is wrapped by `lazy_object_proxy.Proxy`. The actual execution of `expensive_function` is delayed until `obj` is accessed for the first time (e.g., when printed). Subsequent accesses use the cached result without re-executing the wrapped function. [4, 6]

import lazy_object_proxy
import time

def expensive_function():
    """Simulates an expensive operation."""
    print('Starting expensive calculation...')
    time.sleep(2) # Simulate work
    print('Finished expensive calculation.')
    return 'Expensive Result'

# The expensive_function is not called yet
obj = lazy_object_proxy.Proxy(expensive_function)

print('Proxy object created, but function not called yet.')

# The function is called only when the object is actually used
print(f'First access: {obj}') # This will trigger expensive_function
print(f'Second access: {obj}') # This will use the cached result