Table registry utilities#
TableRegistry and configure_all() support
deferred construction workflows: building table shells before metadata is known,
and caching fully configured instances for heterogeneous batch calculations.
Neither is required for batch — they are convenience utilities for building a list of configured table instances without aliasing or redundant construction.
For narrative examples, see Deferred construction: pending, configure, and TableRegistry and TableRegistry — stable instance cache for heterogeneous batch in Using Actuarial Tables. Recipe 18 in Cookbook shows a full heterogeneous portfolio with the functional batch API.
When to use which tool#
Situation |
Recommended approach |
Code example |
|---|---|---|
Same cohort (or duration) processed one group at a time |
|
|
Vectorial zip on sex with a shared deferred cohort |
|
Deferred construction: pending, configure, and TableRegistry § |
Mixed demographics in one batch, keys built incrementally |
||
Large portfolio; all unique |
|
|
Study grid / cartesian parameter sweep |
|
|
Few distinct cohorts; assemble list by hand |
Vectorial zip constructor |
|
Very large portfolio; memory constrained |
|
|
Small portfolio; metadata known per row |
Direct constructor in a list comp |
|
Select table; different duration per policy |
|
TableRegistry — stable instance cache for heterogeneous batch (Using Actuarial Tables); recipe 18 |
Same demographic key; different interest rate |
Pass |
Tip
TableRegistry is a convenience wrapper around the same idea as the
lookup dict pattern — lazy get_or_create()
with LRU instead of building every unique key in one constructor call.
See also
Batch Calculations — Pending tables in batch; cohort/duration portfolio patterns.\
DecrementTable — Base class configure() and batch_update().
TableRegistry#
- class lactuca.TableRegistry(table_class: object = None, *, maxsize: int = 256)#
Cache of fully-configured actuarial table instances keyed by
TableKey.TableRegistryis a lightweight dict wrapper that prevents aliasing when building per-policy table lists for heterogeneous batch calculations: policies that share the same (table_name, sex, cohort, duration, unisex_blend) combination receive the same object, not independent copies.Note
TableRegistryis intended for single-life tables only; it does not accept multi-life configurations. Usereturn_dict=Truein the vectorial constructor for simple homogeneous families.- Parameters:
table_class (LifeTable, DisabilityTable, ExitTable, or None, optional) – Default concrete table class for
get_or_create()(e.g.LifeTable).Nonemeans the class must be passed on eachget_or_create()call. AbstractDecrementTableis rejected.maxsize (int, optional) – Maximum number of cached table instances (LRU eviction). Default is 256.
- Raises:
TypeError – If table_class is not a concrete
DecrementTablesubclass.ValueError – If maxsize is not positive.
Notes
The cache key combines the concrete table class with the demographic tuple
(table_name, sex, cohort, duration, unisex_blend)— the same fields asTableKey.interest_rateis not part of the key. Extra constructor kwargs (e.g.interest_rate) are applied only on first construction; cache hits return the existing instance unchanged.The cache is instance-scoped and bounded (LRU, default
maxsize=256). It is not cleared byreset()— callclear()explicitly when you need an empty registry.Instances stored in the registry are not mutated by the caller after construction — each unique key maps to exactly one stable object, avoiding the aliasing footgun present when a single mutable instance is shared across policies with different parameters.
The registry is not thread-safe: concurrent access from multiple threads may produce duplicate instances. For multi-threaded workloads, create one registry per thread or add external locking.
See also
configure()Per-instance configuration for sequential homogeneous groups.
configure_allApply the same configuration to a collection of pending tables.
Examples
>>> from lactuca import LifeTable, TableRegistry >>> reg = TableRegistry() >>> lt_m = reg.get_or_create(LifeTable, 'PER2020_Ind_1o', 'm', cohort=1972) >>> lt_m2 = reg.get_or_create(LifeTable, 'PER2020_Ind_1o', 'm', cohort=1972) >>> lt_m is lt_m2 True
- clear() None#
Remove all cached entries.
- get_or_create(table_class: object, table_name: str, sex: Literal['m', 'f', 'u'], *, cohort: int | None = None, duration: object = None, unisex_blend: object = None, interest_rate: object = None, **extra_kwargs: object) DecrementTable#
Return a cached instance or create a new one.
- Parameters:
table_class (LifeTable, DisabilityTable, ExitTable, or None) – Concrete table class to instantiate (e.g.
LifeTable). IfNone, the registry-level default from construction is used. AbstractDecrementTableis rejected.table_name (str) – Actuarial table file name (without
.ltk).sex (SexLiteral) – Sex identifier:
'm','f', or'u'.cohort (int or None, optional) – Birth cohort year for generational tables.
duration (int, 'ult', or None, optional) – Select-table duration.
unisex_blend (float or None, optional) – Male weight for unisex blending.
interest_rate (float, InterestRate, or None, optional) – Default interest rate for
LifeTableconstruction. Not part of the cache key; applied only on first construction.**extra_kwargs (object) – Additional keyword arguments forwarded to the constructor on first construction only (cache hits ignore these).
- Returns:
Cached or newly created table instance.
- Return type:
- Raises:
TypeError – If
table_classisNoneand no default was set at registry construction time, if table_class is not a class, if it is not aDecrementTablesubclass, or if it is abstract.
Notes
The cache key combines the concrete table class with
(table_name, sex, cohort, duration, unisex_blend).interest_rateand otherextra_kwargsare not part of the key. If the same demographic key is requested with different extra kwargs, the cached instance is returned unchanged (extra kwargs are only applied on first construction).See also
TableRegistryClass-level documentation and thread-safety notes.
configure_allApply the same configuration to a collection of pending tables.
configure_all#
- lactuca.configure_all(tables: Sequence[DecrementTable] | tuple | dict, *, sex: Literal['m', 'f', 'u'] | None = None, cohort: int | None = None, duration: object = None, unisex_blend: object = None, interest_rate: object = None) Sequence[DecrementTable] | tuple | dict#
Apply
configure()to a collection of tables.Convenience wrapper that calls
table.configure(**kwargs)on every item in tables. Accepts plain sequences (lists, tuples) andreturn_dictdictionaries (only the values are configured). All tables share the same configuration arguments.- Parameters:
tables (sequence of DecrementTable, tuple, or dict) – Tables to configure. A
dictreturned byreturn_dict=Trueis accepted; only thedict.values()are updated.sex ({'m', 'f', 'u'} or None, optional) – Sex for calculations.
Nonemeans omit (keep current value per table).cohort (int or None, optional) – Birth cohort year for generational tables.
Nonemeans omit.duration (int, 'ult', or None, optional) – Select-table duration.
Nonemeans omit.unisex_blend (float or None, optional) – Male weight for unisex blending.
Nonemeans omit.interest_rate (float, InterestRate, or None, optional) – Default interest rate for
LifeTableinstances.Nonemeans omit. Ignored byDecrementTablesubclasses that do not overrideconfigure().
- Returns:
The same tables container, after in-place configuration (chainable).
- Return type:
sequence of DecrementTable, tuple, or dict
- Raises:
ValueError – If no configuration keyword is supplied, or if any table raises inside its
configure()call; tables already processed before the failure remain configured (no global rollback).TypeError – If tables is not a sequence or dict.
Notes
The operation is atomic per instance (each
configure()call rolls back on failure), but there is no global rollback: if the second table in a list of three fails, the first is already configured.The typical use-case is completing pending tables that were created with
sex=["m", "f"]vectorially and share a commoncohortorduration:lt_m, lt_f = LifeTable('PER2020_Ind_1o', ['m', 'f'], pending=True) configure_all((lt_m, lt_f), cohort=1975)
See also
configure()Per-instance atomic configuration.
TableRegistryCache of fully-configured instances for heterogeneous batches.
Examples
>>> from lactuca import LifeTable, configure_all >>> tables = LifeTable('PER2020_Ind_1o', ['m', 'f'], pending=True) >>> configure_all(tables, cohort=1975)