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

pending=True + configure() per group

recipe 17 (Cookbook)

Vectorial zip on sex with a shared deferred cohort

pending=True + configure_all()

Deferred construction: pending, configure, and TableRegistry § configure_all() (Using Actuarial Tables)

Mixed demographics in one batch, keys built incrementally

TableRegistry + get_or_create()

recipe 18 (Cookbook)

Large portfolio; all unique (sex, cohort) pairs known upfront

return_dict=True + TableKey lookup

lookup dict (Batch Calculations)

Study grid / cartesian parameter sweep

return_dict=True + cartesian=True

return_dict lookup (Batch Calculations)

Few distinct cohorts; assemble list by hand

Vectorial zip constructor

few distinct cohorts (Batch Calculations)

Very large portfolio; memory constrained

groupby + one instance + setters

memory-optimal (Batch Calculations)

Small portfolio; metadata known per row

Direct constructor in a list comp

[LifeTable(..., cohort=p["cohort"]) for p in policies]

Select table; different duration per policy

TableRegistry (duration in cache key)

TableRegistry — stable instance cache for heterogeneous batch (Using Actuarial Tables); recipe 18

Same demographic key; different interest rate

Pass ir= to the batch method

multi-table batch (Batch Calculations)

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.

TableRegistry is 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

TableRegistry is intended for single-life tables only; it does not accept multi-life configurations. Use return_dict=True in the vectorial constructor for simple homogeneous families.

Parameters:
Raises:
  • TypeError – If table_class is not a concrete DecrementTable subclass.

  • 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 as TableKey. interest_rate is 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 by reset() — call clear() 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_all

Apply 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). If None, the registry-level default from construction is used. Abstract DecrementTable is 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 LifeTable construction. 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:

DecrementTable

Raises:

TypeError – If table_class is None and no default was set at registry construction time, if table_class is not a class, if it is not a DecrementTable subclass, or if it is abstract.

Notes

The cache key combines the concrete table class with (table_name, sex, cohort, duration, unisex_blend). interest_rate and other extra_kwargs are 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

TableRegistry

Class-level documentation and thread-safety notes.

configure_all

Apply 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) and return_dict dictionaries (only the values are configured). All tables share the same configuration arguments.

Parameters:
  • tables (sequence of DecrementTable, tuple, or dict) – Tables to configure. A dict returned by return_dict=True is accepted; only the dict.values() are updated.

  • sex ({'m', 'f', 'u'} or None, optional) – Sex for calculations. None means omit (keep current value per table).

  • cohort (int or None, optional) – Birth cohort year for generational tables. None means omit.

  • duration (int, 'ult', or None, optional) – Select-table duration. None means omit.

  • unisex_blend (float or None, optional) – Male weight for unisex blending. None means omit.

  • interest_rate (float, InterestRate, or None, optional) – Default interest rate for LifeTable instances. None means omit. Ignored by DecrementTable subclasses that do not override configure().

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 common cohort or duration:

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.

TableRegistry

Cache 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)