Skip to main content

build status pre-commit.ci status

lazy-static

lazy module constants -- think lazy imports but for assignments

roughly named after the (deprecated) rust crate lazy_static

installation

pip install lazy-static

why ?

python 3.15 adds lazy imports which are neat but are a little too easy to accidentally make eager.

take this small example for a little wrapper around pyyaml:

import functools

lazy import yaml

loads = functools.partial(yaml.load, Loader=yaml.CSafeLoader)

did you catch the bug? yeah that import isn't lazy due to accessing attributes!

it would be great if I could do:

lazy loads = functools.partial(yaml.load, Loader=yaml.CSafeLoader)

but there's no such thing...1 unless...

Usage

lazy-static adds a single api: @lazy_static.lazy

taking a simple example:

import argparse
from lazy_static import lazy

@lazy
def computed_once() -> int:
    print('computing!')
    return 5 * 5 * 5

def main() -> int:
    parser = argparse.ArgumentParser()
    parser.parse_args()  # just for `--help`
    print(f'got {computed_once}')
    return 0

if __name__ == '__main__':
    raise SystemExit(main())

the lazy attribute is deferred when not accessed:

$ python3 t.py --help
usage: t.py [-h]

options:
  -h, --help  show this help message and exit

but acts like a normal variable otherwise!

$ python3 t.py
computing!
got 125

it even works with static typing!

$ diff -u t.py.bak t.py
--- t.py.bak    2026-07-24 17:47:14.278681851 -0400
+++ t.py    2026-07-24 17:47:22.759961815 -0400
@@ -10,6 +10,7 @@
     parser = argparse.ArgumentParser()
     parser.parse_args()  # just for `--help`
     print(f'got {computed_once}')
+    reveal_type(computed_once)
     return 0

 if __name__ == '__main__':
$ mypy t.py
t.py:13: note: Revealed type is "int"
Success: no issues found in 1 source file

if we take the earlier example we can define our loads partial lazily while preserving the lazy import!

import functools

from lazy_static import lazy
lazy import yaml

@lazy
def loads():
    return functools.partial(yaml.loads, Loader=yaml.CSafeLoader)
  1. yes yes you can do stuff with @functools.cache but that adds an ugly function call! ↩

Metadata

Release files for lazy-static 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lazy-static 1.0.0
File Size Uploaded
lazy_static-1.0.0.tar.gz 3.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lazy-static 1.0.0
File Interpreter ABI Platform
lazy_static-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 7.5 kB

Release files / lazy_static-1.0.0.tar.gz

Download URL lazy_static-1.0.0.tar.gz
Size 3.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ca26d0686d9883907b89e0051ad2cc4a772bde177c493c585eb598a49dc8a75e
BLAKE2b-256 checksum
How to use checksums
6d345180ed8c59e0a3e1c5ce8f163259663cb89f39eacd94a924d9a2ddff4d03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / lazy_static-1.0.0-py3-none-any.whl

Download URL lazy_static-1.0.0-py3-none-any.whl
Size 3.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ba062d9a69929a8dee97c408eed0c9f8f034dd0842ce17a5544b78c3b74b9ad0
BLAKE2b-256 checksum
How to use checksums
3990002c3e89bf5516a2d831821e6f102c430c0212e14882da6b1f6e9b7a0e91
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page