Created
July 1, 2024 18:52
-
-
Save Tuanm/bec6296e234fe922b68eeab6385c78a6 to your computer and use it in GitHub Desktop.
Create Python Instance Lazily
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dataclasses | |
import threading | |
from typing import Any, Callable, Optional, Type, TypeVar, Union | |
V = TypeVar("V") | |
def lazy(init: Union[Type[V], Callable[..., V]], *args, **kwargs) -> V: | |
""" | |
Returns a lazy instance for a specific type. | |
Parameters: | |
- init (class/function): type or function to create the instance. | |
""" | |
if init is None or not callable(init): | |
raise TypeError("Type must not be None or uncallable") | |
@dataclasses.dataclass | |
class _Holder: | |
"""Closure instance for holding actual object.""" | |
initialized: bool | |
lock: threading.Lock | |
obj: Optional[V] | |
"""Actual object.""" | |
_holder = _Holder(False, threading.Lock(), None) | |
def _init_obj(): | |
"""Actually initializes holding object.""" | |
if not _holder.initialized: | |
with _holder.lock: | |
if not _holder.initialized: | |
_holder.obj = init(*args, **kwargs) | |
_holder.initialized = True | |
class _Object: | |
def __getattribute__(self, name: str) -> Any: | |
_init_obj() | |
return getattr(_holder.obj, name) | |
def __str__(self): | |
_init_obj() | |
return str(_holder.obj) | |
return _Object() # type: ignore |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dataclasses | |
import time | |
from .lib import lazy | |
@dataclasses.dataclass | |
class Object: | |
value: str | |
def create_heavy_object(): | |
time.sleep(20) | |
obj = Object("heavy") | |
return obj | |
# lazy function call | |
heavy_object_1 = lazy(create_heavy_object) | |
print(heavy_object_1) | |
# lazy type initialization | |
heavy_object_2 = lazy(Object) | |
print(heavy_object_2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment