Skip to content

API reference

Classes

signified.Signal

Bases: Signal[T], Variable[T]

Mutable state.

Signal stores a value and notifies observers when that value changes. The value property is read/write:

  • reading value returns the exact stored value
  • assigning value updates the stored value and notifies observers if it changed

Assigning any other public attribute forwards the write to the wrapped object; see setattr.

Parameters:

Name Type Description Default
value T

Value to wrap.

required
equal Callable[[T, T], bool] | None

Optional equal(previous, new) -> bool. When it returns True, an assignment counts as unchanged: the previous object is kept and observers are not notified. See also rx.with_equal.

None
Example
>>> count = Signal(1)
>>> doubled = count * 2
>>> doubled.value
2
>>> count.value = 3
>>> doubled.value
6

Attribute writes reach the wrapped object and notify observers:

>>> class Person:
...     def __init__(self, name: str):
...         self.name = name
...     def greet(self) -> str:
...         return f"Hi, I'm {self.name}!"
>>> s = Signal(Person("Alice"))
>>> result = s.greet()
>>> result.value
"Hi, I'm Alice!"
>>> s.name = "Bob"
>>> result.value
"Hi, I'm Bob!"

value property writable

value

The current value.

Getting this property returns the stored Python value. Setting it updates the stored value and notifies observers if the value changed.

at

at(value)

Temporarily set the signal to a given value within a context.

Restores the previous value when the context exits, even if an exception is raised.

The previous version is restored along with the previous value, so a dependent that was not read inside the context is not left needing a recompute. Dependents read inside the context recompute as usual. If the signal is written again inside the context, exit falls back to an ordinary assignment.

A Computed cannot change signals, so inside one at() raises RuntimeError unless value is the value the signal already holds. To read a value as if the signal held another value, use sample.

Parameters:

Name Type Description Default
value T

The temporary value to set.

required
Example
>>> s = Signal(1)
>>> with s.at(99):
...     print(s.value)
99
>>> s.value
1

update

update()

Force a notification to all observers unconditionally.

Unlike assigning to .value, this does not check whether the stored value has changed. Use this when the contained object has been mutated in-place and change detection cannot detect the mutation (e.g. appending to a list stored in the signal).

Warning

Every downstream Computed that depends on this signal will recompute on its next .value read, even if the underlying data is unchanged. Prefer assigning to .value when possible.

__setattr__

__setattr__(name, value)

Forward a public attribute write to the wrapped object and notify.

Private names and Signal's own attributes (such as value) are assigned on the wrapper. Any other name must already exist on the wrapped object; the write is applied there and observers are notified, exactly like signal[key] = value. Unknown names raise AttributeError instead of silently creating an attribute on the wrapper.

Only Signal forwards writes, because only a Signal owns its value. A Computed holds a cache that the next refresh replaces, so writing through it would mutate state it does not own.

Parameters:

Name Type Description Default
name str

The attribute name to assign.

required
value Any

The value to assign.

required

Raises:

Type Description
AttributeError

If the wrapped object has no attribute name.

__setitem__

__setitem__(key, value)

Set an item on the wrapped list or dict and notify observers.

Assigning through the Signal rather than through signal.value is what notifies dependents: in-place mutation of the wrapped object is not observed on its own. Only Signal forwards item assignment, because only a Signal owns its value; a Computed holds a cache that the next refresh replaces.

Parameters:

Name Type Description Default
key Any

The key to change.

required
value Any

The value to set it to.

required

Raises:

Type Description
TypeError

If the wrapped value is not a list or dict.

Example
>>> s = Signal([1, 2, 3])
>>> result = computed(sum)(s)
>>> result.value
6
>>> s[1] = 4
>>> result.value
8

__delitem__

__delitem__(key)

Delete an item from the wrapped list or dict and notify observers.

The mirror of setitem, and subject to the same rule: deleting through the Signal is what notifies dependents, and only a Signal forwards item deletion.

Parameters:

Name Type Description Default
key Any

The key to delete.

required

Raises:

Type Description
TypeError

If the wrapped value is not a list or dict.

Example
>>> s = Signal([1, 2, 3])
>>> result = computed(sum)(s)
>>> result.value
6
>>> del s[1]
>>> result.value
4

signified.Computed

Bases: Computed[T], Variable[T]

Reactive value derived from a computation.

Computed lazily re-runs its function and updates its value whenever a dependency changes. Dependencies are inferred automatically from which reactive values are read during evaluation.

In most cases Computed instances should be created implicitly by using overloaded operators or the computed decorator rather than directly using the Computed class.

Unlike Signal, Computed.value is read-only. Ordinary exceptions are cached like values and re-raised on reads until a dependency changes or invalidate() forces another evaluation.

Parameters:

Name Type Description Default
f Callable[[], T]

Zero-argument function used to compute the current value.

required
equal Callable[[T, T], bool] | None

Optional equal(previous, current) -> bool. When it returns True, a recomputed value counts as unchanged: the previous object is kept and dependents are not invalidated. By default, built-in scalars compare by value and other objects by identity. Reads inside equal are not tracked, and an exception it raises is cached like an exception from f. See also rx.with_equal.

None
Example
>>> count = Signal(2)
>>> squared = Computed(lambda: count.value ** 2)
>>> squared.value
4
>>> count.value = 5
>>> squared.value
25

With equal, a new but equal result keeps dependents clean:

>>> count = Signal(2)
>>> parity = Computed(lambda: [count.value % 2], equal=lambda a, b: a == b)
>>> first = parity.value
>>> count.value = 4
>>> parity.value is first
True

value property

value

Get the current value, recomputing lazily when stale.

invalidate

invalidate()

Force a full recomputation on the next .value read.

Use this when a reactive attribute is replaced with a new object and the normal change-detection path may not pick up the change. Unlike a regular update, this always triggers re-evaluation regardless of whether dependencies appear unchanged.

Warning

This method is fragile and should be a last resort. Incorrect use can cause unnecessary recomputation or missed updates. Prefer assigning to .value whenever possible, as this triggers the standard change-detection path.

Example
>>> external = {"value": 1}
>>> c = Computed(lambda: external["value"])
>>> c.value
1
>>> external["value"] = 99  # mutation not tracked by reactivity
>>> c.value  # still cached
1
>>> c.invalidate()
>>> c.value
99

signified.Binding

Bases: Computed[T]

A reactive value whose source you can switch.

A Binding either holds a plain value or follows a Signal, Computed, or another Binding. Assign to value to switch: a reactive value is followed, and a plain value is held. Calculations built from the binding keep working across switches, and recalculate only if its value changes.

Parameters:

Name Type Description Default
source T | ReactiveValue[T]

A reactive value to follow, or a plain value to hold.

required

value property writable

value

The current source's value. Assigning selects a plain value or follows a reactive source.

source property

source

Return the exact current source without resolving it.

set

set(source)

Select a plain value or follow a reactive source.

derive

derive(build)

Build and select a source from the exact pre-rebind source.

Capturing the old source prevents the common cycle created by building a new computation from the Binding that will receive that computation.

at

at(value)

Temporarily follow a private Signal holding value.

The previous source is restored when the context exits, even if an exception is raised. Like Signal.at, a dependent that did not read the binding inside the context is not left needing a recompute.

Parameters:

Name Type Description Default
value T

The temporary plain value.

required

signified.Effect

Bases: Effect

Run a function now, and again whenever the reactive values it read change.

Each run records the reactive values fn reads, through .value or unref. A change to any of them runs fn again. Only reads from the latest run count: in Effect(lambda: x.value if flag.value else y.value), while flag is true, changing y does nothing.

The first run happens immediately, or when the enclosing batch exits. Several changes before a run share one run, and a run is skipped if nothing it read actually changed, such as a calculation that recalculated to the same result.

Warning

Keep a reference to the effect for as long as it should run. A discarded effect is garbage collected and stops:

Effect(lambda: print(s.value))      # runs once, then never again
e = Effect(lambda: print(s.value))  # runs on every change

Call dispose to stop it explicitly.

Parameters:

Name Type Description Default
fn Callable[[], None]

Zero-argument function to run for its side effects.

required
Example
>>> seen = []
>>> s = Signal(1)
>>> e = Effect(lambda: seen.append(s.value))
>>> seen
[1]
>>> s.value = 2
>>> s.value = 3
>>> seen
[1, 2, 3]
>>> e.dispose()
>>> s.value = 99
>>> seen
[1, 2, 3]

dispose

dispose()

Stop this effect, including any pending run. Safe to repeat.

signified.Variable

Bases: _ReactiveMixIn[T]

Common base of reactive values.

Signal, Computed, and Binding extend this class. You should use them directly.

Variable is only exposed for type hinting or subclassing purposes.

The rx namespace

Every signal, computed value, and binding has an rx property. It holds reactive versions of operations that Python syntax can't make reactive, such as identity checks, membership, and choosing between two values:

Helper methods available under signal_or_computed.rx.

T is the source's value type and Source its exact reactive type, so helpers that return the source keep it as Signal, Computed, or Binding.

map

map(fn)

Return a reactive value by applying fn to the source.

Parameters:

Name Type Description Default
fn Callable[[T], R]

Function used to transform the current source value.

required

Returns:

Type Description
Computed[R]

A reactive value for fn(source.value).

Example
>>> s = Signal(4)
>>> doubled = s.rx.map(lambda x: x * 2)
>>> doubled.value
8
>>> s.value = 5
>>> doubled.value
10

effect

effect(fn)

Call fn with the source's value now, and again whenever it changes.

A shortcut for Effect(lambda: fn(source.value)). Inside batch, calls wait until the batch exits.

Keep the returned Effect for as long as fn should run, and call dispose to stop it.

Parameters:

Name Type Description Default
fn Callable[[T], None]

Called with the source's current value.

required

Returns:

Type Description
'Effect'

The Effect that calls fn.

Example
>>> seen = []
>>> s = Signal(1)
>>> e = s.rx.effect(seen.append)
>>> seen
[1]
>>> s.value = 2
>>> s.value = 3
>>> seen
[1, 2, 3]
>>> e.dispose()
>>> s.value = 99
>>> seen
[1, 2, 3]

tap

tap(fn)

Lazily call fn on evaluation and pass through the source value.

This returns a cached Computed: repeated reads without invalidation do not repeat the callback, and unread intermediate values are skipped. Keep the result alive. Use rx.effect for eager side effects, or untracked() to inspect a value without subscribing.

Example
>>> seen = []
>>> s = Signal(1)
>>> passthrough = s.rx.tap(seen.append)
>>> s.value = 2
>>> seen
[]
>>> passthrough.value
2
>>> seen
[2]

with_equal

with_equal(equal)

Set the custom equality the source uses to decide whether it changed.

When equal(previous, new) returns True, a new value counts as unchanged: the previous object is kept and dependents are not invalidated. This is the same as passing equal= to Signal or Computed, and also works on values built by operators, computed, and rx.map. It applies to later changes only. Pass None to restore the default (built-in scalars by value, other objects by identity).

The source is changed in place and returned, so the call can end an expression: m = (rotation @ scale).rx.with_equal(np.array_equal).

Example
>>> source = Signal(1)
>>> parity = source.rx.map(lambda value: [value % 2]).rx.with_equal(lambda a, b: a == b)
>>> first = parity.value
>>> source.value = 3
>>> parity.value is first
True

len

len()

Return a reactive value for len(source.value).

Returns:

Type Description
Computed[int]

A reactive value for len(source.value).

Example
>>> s = Signal([1, 2, 3])
>>> length = s.rx.len()
>>> length.value
3
>>> s.value = [10]
>>> length.value
1

is_

is_(other)

Return a reactive value for identity check source.value is other.

Parameters:

Name Type Description Default
other Any

Value to compare against with identity semantics.

required

Returns:

Type Description
Computed[bool]

A reactive value for source.value is other.

Example
>>> marker = object()
>>> s = Signal(marker)
>>> result = s.rx.is_(marker)
>>> result.value
True
>>> s.value = object()
>>> result.value
False

is_not

is_not(other)

Return a reactive value for identity check source.value is not other.

Parameters:

Name Type Description Default
other Any

Value to compare against with identity semantics.

required

Returns:

Type Description
Computed[bool]

A reactive value for source.value is not other.

Example
>>> marker = object()
>>> s = Signal(marker)
>>> result = s.rx.is_not(marker)
>>> result.value
False
>>> s.value = object()
>>> result.value
True

in_

in_(container)

Return a reactive value for containment check source.value in container.

Parameters:

Name Type Description Default
container _MembershipContainer | _ReactiveOf[_MembershipContainer]

Value checked for membership, e.g. list/string/set.

required

Returns:

Type Description
Computed[bool]

A reactive value for source.value in container.

Example
>>> needle = Signal("a")
>>> haystack = Signal("cat")
>>> result = needle.rx.in_(haystack)
>>> result.value
True
>>> needle.value = "z"
>>> result.value
False

contains

contains(other)

Return a reactive value for whether other is in self._source.

Parameters:

Name Type Description Default
other Any

The value to check for containment.

required

Returns:

Type Description
Computed[bool]

A reactive value for other in source.value.

Example
>>> s = Signal([1, 2, 3, 4])
>>> result = s.rx.contains(3)
>>> result.value
True
>>> s.value = [5, 6, 7, 8]
>>> result.value
False

eq

eq(other: _ReactiveOf[Y]) -> Computed[R]
eq(other: Y) -> Computed[R]
eq(other)

Return a reactive value for whether source.value == other.

Parameters:

Name Type Description Default
other Any

Value to compare against.

required

Returns:

Type Description
Computed[Any]

A reactive value for source.value == other.

Example
>>> s = Signal(10)
>>> result = s.rx.eq(10)
>>> result.value
True
>>> s.value = 25
>>> result.value
False

ne

ne(other: _ReactiveOf[Y]) -> Computed[R]
ne(other: Y) -> Computed[R]
ne(other)

Return a reactive value for whether source.value != other.

Comparisons between reactive objects use identity. Use this method to compare their wrapped values without changing how reactive objects behave in sets and dictionaries.

Parameters:

Name Type Description Default
other Any

Value to compare against.

required

Returns:

Type Description
Computed[Any]

A reactive value for source.value != other.

Example
>>> s = Signal(10)
>>> result = s.rx.ne(10)
>>> result.value
False
>>> s.value = 25
>>> result.value
True

where

where(a: HasValue[A], b: HasValue[B]) -> Computed[A]
where(a: HasValue[A], b: HasValue[B]) -> Computed[B]
where(
    a: HasValue[A], b: HasValue[B]
) -> Computed[A | B]
where(a, b)

Return a reactive value for a if source is truthy, else b.

When the source type guarantees truthiness or falsiness (a literal bool, None, or a literal-returning __bool__), the result type narrows to the selected branch. An ordinary Signal[bool] retains both branch types.

Parameters:

Name Type Description Default
a HasValue[A]

The value to return if source is truthy.

required
b HasValue[B]

The value to return if source is falsy.

required

Returns:

Type Description
Computed[Any]

A reactive value for a if source.value else b.

Example
>>> condition = Signal(True)
>>> result = condition.rx.where("Yes", "No")
>>> result.value
'Yes'
>>> condition.value = False
>>> result.value
'No'

as_bool

as_bool() -> Computed[Literal[True]]
as_bool() -> Computed[Literal[False]]
as_bool() -> Computed[bool]
as_bool()

Return a reactive value for the boolean value of self._source.

Note

__bool__ cannot be implemented to return a non-bool, so it is provided as a method.

Returns:

Type Description
Computed[Any]

A reactive value for bool(source.value).

Example
>>> s = Signal(1)
>>> result = s.rx.as_bool()
>>> result.value
True
>>> s.value = 0
>>> result.value
False

Operators

Arithmetic, comparisons, item access, attribute access, and calls on a reactive value return a Computed that follows its operands. The Operators page gives an overview.

Methods for easily creating reactive values.

__getattr__

__getattr__(name: Literal['value', '_value']) -> T
__getattr__(name: str) -> Computed[Any]
__getattr__(name)

Create a reactive value for retrieving an attribute from self.value.

Parameters:

Name Type Description Default
name str

The name of the attribute to access.

required

Returns:

Type Description
Union[T, Computed[Any]]

A reactive value for the attribute access.

Raises:

Type Description
AttributeError

If the attribute doesn't exist.

Note

Type inference is poor whenever __getattr__ is used.

Example
>>> class Person:
...     def __init__(self, name):
...         self.name = name
>>> s = Signal(Person("Alice"))
>>> result = s.name
>>> result.value
'Alice'
>>> s.value = Person("Bob")
>>> result.value
'Bob'

__call__

__call__(*args, **kwargs)

Create a reactive value for calling self.value(*args, **kwargs).

Parameters:

Name Type Description Default
*args P.args

Positional arguments to pass to the callable value.

()
**kwargs P.kwargs

Keyword arguments to pass to the callable value.

{}

Returns:

Type Description
Computed[R]

A reactive value for the function call.

Raises:

Type Description
ValueError

If the value is not callable.

Example
>>> class Person:
...     def __init__(self, name):
...         self.name = name
...     def greet(self):
...         return f"Hi, I'm {self.name}!"
>>> s = Signal(Person("Alice"))
>>> result = s.greet()
>>> result.value
"Hi, I'm Alice!"
>>> s.name = "Bob"
>>> result.value
"Hi, I'm Bob!"

__abs__

__abs__()

Return a reactive value for the absolute value of self.

Returns:

Type Description
Computed[R]

A reactive value for abs(self.value).

Example
>>> s = Signal(-5)
>>> result = abs(s)
>>> result.value
5
>>> s.value = -10
>>> result.value
10

__round__

__round__(ndigits: None = None) -> Computed[int]
__round__(ndigits: int) -> Computed[R]
__round__(ndigits=None)

Return a reactive value for the rounded value of self.

Parameters:

Name Type Description Default
ndigits int | None

Number of decimal places to round to.

None

Returns:

Type Description
Computed[int] | Computed[R]

A reactive value for round(self.value, ndigits).

Example
>>> s = Signal(3.14159)
>>> result = round(s, 2)
>>> result.value
3.14
>>> s.value = 2.71828
>>> result.value
2.72

__ceil__

__ceil__() -> Computed[R]
__ceil__() -> Computed[int]
__ceil__()

Return a reactive value for the ceiling of self.

Returns:

Type Description
Computed[Any]

A reactive value for math.ceil(self.value).

Example
>>> from math import ceil
>>> s = Signal(3.14)
>>> result = ceil(s)
>>> result.value
4
>>> s.value = 2.01
>>> result.value
3

__floor__

__floor__() -> Computed[R]
__floor__() -> Computed[int]
__floor__()

Return a reactive value for the floor of self.

Returns:

Type Description
Computed[Any]

A reactive value for math.floor(self.value).

Example
>>> from math import floor
>>> s = Signal(3.99)
>>> result = floor(s)
>>> result.value
3
>>> s.value = 4.01
>>> result.value
4

__trunc__

__trunc__()

Return a reactive value for the truncated value of self.

Returns:

Type Description
Computed[R]

A reactive value for math.trunc(self.value).

Example
>>> from math import trunc
>>> s = Signal(3.99)
>>> result = trunc(s)
>>> result.value
3
>>> s.value = -4.01
>>> result.value
-4

__neg__

__neg__()

Return a reactive value for the negation of self.

Returns:

Type Description
Computed[R]

A reactive value for -self.value.

Example
>>> s = Signal(5)
>>> result = -s
>>> result.value
-5
>>> s.value = -3
>>> result.value
3

__pos__

__pos__()

Return a reactive value for the positive of self.

Returns:

Type Description
Computed[R]

A reactive value for +self.value.

Example
>>> s = Signal(-5)
>>> result = +s
>>> result.value
-5
>>> s.value = 3
>>> result.value
3

__invert__

__invert__()

Return a reactive value for the bitwise inversion of self.

Returns:

Type Description
Computed[R]

A reactive value for ~self.value.

Example
>>> s = Signal(5)
>>> result = ~s
>>> result.value
-6
>>> s.value = -3
>>> result.value
2

__add__

__add__(other: HasValue[N]) -> Computed[N]
__add__(other: HasValue[N]) -> Computed[N]
__add__(other: _ReactiveOf[Y]) -> Computed[R]
__add__(
    other: _ReactiveOf[_SupportsRadd[T, R]],
) -> Computed[R]
__add__(other: Y) -> Computed[R]
__add__(other: _SupportsRadd[T, R]) -> Computed[R]
__add__(other)

Return a reactive value for the sum of self and other.

Parameters:

Name Type Description Default
other Any

The value to add.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value + other.value.

Example
>>> s = Signal(5)
>>> result = s + 3
>>> result.value
8
>>> s.value = 10
>>> result.value
13

__radd__

__radd__(other: HasValue[N]) -> Computed[N]
__radd__(other: HasValue[N]) -> Computed[N]
__radd__(other: HasValue[timedelta]) -> Computed[D]
__radd__(
    other: _ReactiveOf[_SupportsAdd[T, R]],
) -> Computed[R]
__radd__(other: _ReactiveOf[Y]) -> Computed[R]
__radd__(other: _SupportsAdd[T, R]) -> Computed[R]
__radd__(other: Y) -> Computed[R]
__radd__(other)

Return a reactive value for the sum of self and other.

Parameters:

Name Type Description Default
other Any

The value to add.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value + other.value.

Example
>>> s = Signal(5)
>>> result = 3 + s
>>> result.value
8
>>> s.value = 10
>>> result.value
13

__sub__

__sub__(other: HasValue[N]) -> Computed[N]
__sub__(other: HasValue[N]) -> Computed[N]
__sub__(other: HasValue[timedelta]) -> Computed[D]
__sub__(other: HasValue[D]) -> Computed[timedelta]
__sub__(other: _ReactiveOf[Y]) -> Computed[R]
__sub__(
    other: _ReactiveOf[_SupportsRsub[T, R]],
) -> Computed[R]
__sub__(other: Y) -> Computed[R]
__sub__(other: _SupportsRsub[T, R]) -> Computed[R]
__sub__(other)

Return a reactive value for the difference of self and other.

Parameters:

Name Type Description Default
other Any

The value to subtract.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value - other.value.

Example
>>> s = Signal(10)
>>> result = s - 3
>>> result.value
7
>>> s.value = 15
>>> result.value
12

__rsub__

__rsub__(other: HasValue[N]) -> Computed[N]
__rsub__(other: HasValue[N]) -> Computed[N]
__rsub__(
    other: _ReactiveOf[_SupportsSub[T, R]],
) -> Computed[R]
__rsub__(other: _ReactiveOf[Y]) -> Computed[R]
__rsub__(other: _SupportsSub[T, R]) -> Computed[R]
__rsub__(other: Y) -> Computed[R]
__rsub__(other)

Return a reactive value for the difference of self and other.

Parameters:

Name Type Description Default
other Any

The value to subtract from.

required

Returns:

Type Description
Computed[Any]

A reactive value for other.value - self.value.

Example
>>> s = Signal(10)
>>> result = 15 - s
>>> result.value
5
>>> s.value = 15
>>> result.value
0

__mul__

__mul__(other: HasValue[N]) -> Computed[N]
__mul__(other: HasValue[N]) -> Computed[N]
__mul__(other: _ReactiveOf[Y]) -> Computed[R]
__mul__(
    other: _ReactiveOf[_SupportsRmul[T, R]],
) -> Computed[R]
__mul__(other: Y) -> Computed[R]
__mul__(other: _SupportsRmul[T, R]) -> Computed[R]
__mul__(other)

Return a reactive value for the product of self and other.

Parameters:

Name Type Description Default
other Any

The value to multiply with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value * other.value.

Example
>>> s = Signal(4)
>>> result = s * 3
>>> result.value
12
>>> s.value = 5
>>> result.value
15

__rmul__

__rmul__(other: HasValue[N]) -> Computed[N]
__rmul__(other: HasValue[N]) -> Computed[N]
__rmul__(
    other: _ReactiveOf[_SupportsMul[T, R]],
) -> Computed[R]
__rmul__(other: _ReactiveOf[Y]) -> Computed[R]
__rmul__(other: _SupportsMul[T, R]) -> Computed[R]
__rmul__(other: Y) -> Computed[R]
__rmul__(other)

Return a reactive value for the product of self and other.

Parameters:

Name Type Description Default
other Any

The value to multiply with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value * other.value.

Example
>>> s = Signal(4)
>>> result = 3 * s
>>> result.value
12
>>> s.value = 5
>>> result.value
15

__truediv__

__truediv__(other: HasValue[N]) -> Computed[N]
__truediv__(other: _ReactiveOf[Y]) -> Computed[R]
__truediv__(
    other: _ReactiveOf[_SupportsRtruediv[T, R]],
) -> Computed[R]
__truediv__(other: Y) -> Computed[R]
__truediv__(
    other: _SupportsRtruediv[T, R],
) -> Computed[R]
__truediv__(other)

Return a reactive value for self divided by other.

Parameters:

Name Type Description Default
other Any

The value to use as the divisor.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value / other.value.

Example
>>> s = Signal(20)
>>> result = s / 4
>>> result.value
5.0
>>> s.value = 30
>>> result.value
7.5

__rtruediv__

__rtruediv__(other: HasValue[N]) -> Computed[N]
__rtruediv__(
    other: _ReactiveOf[_SupportsTruediv[T, R]],
) -> Computed[R]
__rtruediv__(other: _ReactiveOf[Y]) -> Computed[R]
__rtruediv__(
    other: _SupportsTruediv[T, R],
) -> Computed[R]
__rtruediv__(other: Y) -> Computed[R]
__rtruediv__(other)

Return a reactive value for self divided by other.

Parameters:

Name Type Description Default
other Any

The value to use as the divisor.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value / other.value.

Example
>>> s = Signal(2)
>>> result = 30 / s
>>> result.value
15.0
>>> s.value = 3
>>> result.value
10.0

__floordiv__

__floordiv__(other: HasValue[N]) -> Computed[N]
__floordiv__(other: _ReactiveOf[Y]) -> Computed[R]
__floordiv__(
    other: _ReactiveOf[_SupportsRfloordiv[T, R]],
) -> Computed[R]
__floordiv__(other: Y) -> Computed[R]
__floordiv__(
    other: _SupportsRfloordiv[T, R],
) -> Computed[R]
__floordiv__(other)

Return a reactive value for the floor division of self by other.

Parameters:

Name Type Description Default
other Any

The value to use as the divisor.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value // other.value.

Example
>>> s = Signal(20)
>>> result = s // 3
>>> result.value
6
>>> s.value = 25
>>> result.value
8

__rfloordiv__

__rfloordiv__(other: HasValue[N]) -> Computed[N]
__rfloordiv__(
    other: _ReactiveOf[_SupportsFloordiv[T, R]],
) -> Computed[R]
__rfloordiv__(other: _ReactiveOf[Y]) -> Computed[R]
__rfloordiv__(
    other: _SupportsFloordiv[T, R],
) -> Computed[R]
__rfloordiv__(other: Y) -> Computed[R]
__rfloordiv__(other)

Return a reactive value for the floor division of other by self.

Parameters:

Name Type Description Default
other Any

The value to use as the numerator.

required

Returns:

Type Description
Computed[Any]

A reactive value for other.value // self.value.

Example
>>> s = Signal(3)
>>> result = 10 // s
>>> result.value
3
>>> s.value = 4
>>> result.value
2

__mod__

__mod__(other: HasValue[N]) -> Computed[N]
__mod__(other: _ReactiveOf[Y]) -> Computed[R]
__mod__(
    other: _ReactiveOf[_SupportsRmod[T, R]],
) -> Computed[R]
__mod__(other: Y) -> Computed[R]
__mod__(other: _SupportsRmod[T, R]) -> Computed[R]
__mod__(other)

Return a reactive value for self modulo other.

Parameters:

Name Type Description Default
other Any

The divisor.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value % other.value.

Example
>>> s = Signal(17)
>>> result = s % 5
>>> result.value
2
>>> s.value = 23
>>> result.value
3

__rmod__

__rmod__(other: HasValue[N]) -> Computed[N]
__rmod__(
    other: _ReactiveOf[_SupportsMod[T, R]],
) -> Computed[R]
__rmod__(other: _ReactiveOf[Y]) -> Computed[R]
__rmod__(other: _SupportsMod[T, R]) -> Computed[R]
__rmod__(other: Y) -> Computed[R]
__rmod__(other)

Return a reactive value for other modulo self.

Parameters:

Name Type Description Default
other Any

The dividend.

required

Returns:

Type Description
Computed[Any]

A reactive value for other.value % self.value.

Example
>>> s = Signal(3)
>>> result = 10 % s
>>> result.value
1
>>> s.value = 4
>>> result.value
2

__pow__

__pow__(other: HasValue[N]) -> Computed[N]
__pow__(other: HasValue[N]) -> Computed[N]
__pow__(other: _ReactiveOf[Y]) -> Computed[R]
__pow__(
    other: _ReactiveOf[_SupportsRpow[T, R]],
) -> Computed[R]
__pow__(other: Y) -> Computed[R]
__pow__(other: _SupportsRpow[T, R]) -> Computed[R]
__pow__(other)

Return a reactive value for self raised to the power of other.

Parameters:

Name Type Description Default
other Any

The exponent.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value ** other.value.

Example
>>> s = Signal(2)
>>> result = s ** 3
>>> result.value
8
>>> s.value = 3
>>> result.value
27

__rpow__

__rpow__(other: HasValue[N]) -> Computed[N]
__rpow__(other: HasValue[N]) -> Computed[N]
__rpow__(
    other: _ReactiveOf[_SupportsPow[T, R]],
) -> Computed[R]
__rpow__(other: _ReactiveOf[Y]) -> Computed[R]
__rpow__(other: _SupportsPow[T, R]) -> Computed[R]
__rpow__(other: Y) -> Computed[R]
__rpow__(other)

Return a reactive value for self raised to the power of other.

Parameters:

Name Type Description Default
other Any

The base.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value ** other.value.

Example
>>> s = Signal(2)
>>> result = 3 ** s
>>> result.value
9
>>> s.value = 3
>>> result.value
27

__matmul__

__matmul__(other: _ReactiveOf[Y]) -> Computed[R]
__matmul__(
    other: _ReactiveOf[_SupportsRmatmul[T, R]],
) -> Computed[R]
__matmul__(other: Y) -> Computed[R]
__matmul__(other: _SupportsRmatmul[T, R]) -> Computed[R]
__matmul__(other)

Return a reactive value for the matrix multiplication of self and other.

Parameters:

Name Type Description Default
other Any

The value to multiply with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value @ other.value.

Example
>>> import numpy as np
>>> s = Signal(np.array([1, 2]))
>>> result = s @ np.array([[1, 2], [3, 4]])
>>> result.value
array([ 7, 10])
>>> s.value = np.array([2, 3])
>>> result.value
array([11, 16])

__rmatmul__

__rmatmul__(
    other: _ReactiveOf[_SupportsMatmul[T, R]],
) -> Computed[R]
__rmatmul__(other: _ReactiveOf[Y]) -> Computed[R]
__rmatmul__(other: _SupportsMatmul[T, R]) -> Computed[R]
__rmatmul__(other: Y) -> Computed[R]
__rmatmul__(other)

Return a reactive value for the matrix multiplication of other and self.

Note

NumPy arrays on the left defer to this method because reactive values opt out of NumPy's ufunc dispatch. The result is a single Computed.

Parameters:

Name Type Description Default
other Any

The value to multiply with.

required

Returns:

Type Description
Computed[Any]

A reactive value for other.value @ self.value.

Example
>>> class Row:
...     def __init__(self, values):
...         self.values = values
...     def __matmul__(self, other):
...         if not isinstance(other, Row):
...             return NotImplemented
...         return sum(a * b for a, b in zip(self.values, other.values))
>>> s = Signal(Row([3, 4]))
>>> result = Row([1, 2]) @ s
>>> result.value
11
>>> s.value = Row([1, 1])
>>> result.value
3

__and__

__and__(other: HasValue[N]) -> Computed[N]
__and__(other: _ReactiveOf[Y]) -> Computed[R]
__and__(
    other: _ReactiveOf[_SupportsRand[T, R]],
) -> Computed[R]
__and__(other: Y) -> Computed[R]
__and__(other: _SupportsRand[T, R]) -> Computed[R]
__and__(other)

Return a reactive value for the bitwise AND of self and other.

Parameters:

Name Type Description Default
other Any

The value to AND with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value & other.value.

Example
>>> s = Signal(True)
>>> result = s & False
>>> result.value
False
>>> s.value = True
>>> result.value
False

__rand__

__rand__(other: HasValue[N]) -> Computed[N]
__rand__(
    other: _ReactiveOf[_SupportsAnd[T, R]],
) -> Computed[R]
__rand__(other: _ReactiveOf[Y]) -> Computed[R]
__rand__(other: _SupportsAnd[T, R]) -> Computed[R]
__rand__(other: Y) -> Computed[R]
__rand__(other)

Return a reactive value for the bitwise AND of self and other.

Parameters:

Name Type Description Default
other Any

The value to AND with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value and other.value.

Example
>>> s = Signal(True)
>>> result = False & s
>>> result.value
False
>>> s.value = True
>>> result.value
False

__or__

__or__(other: HasValue[N]) -> Computed[N]
__or__(other: _ReactiveOf[Y]) -> Computed[R]
__or__(
    other: _ReactiveOf[_SupportsRor[T, R]],
) -> Computed[R]
__or__(other: Y) -> Computed[R]
__or__(other: _SupportsRor[T, R]) -> Computed[R]
__or__(other)

Return a reactive value for the bitwise OR of self and other.

Parameters:

Name Type Description Default
other Any

The value to OR with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value or other.value.

Example
>>> s = Signal(False)
>>> result = s | True
>>> result.value
True
>>> s.value = True
>>> result.value
True

__ror__

__ror__(other: HasValue[N]) -> Computed[N]
__ror__(
    other: _ReactiveOf[_SupportsOr[T, R]],
) -> Computed[R]
__ror__(other: _ReactiveOf[Y]) -> Computed[R]
__ror__(other: _SupportsOr[T, R]) -> Computed[R]
__ror__(other: Y) -> Computed[R]
__ror__(other)

Return a reactive value for the bitwise OR of self and other.

Parameters:

Name Type Description Default
other Any

The value to OR with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value or other.value.

Example
>>> s = Signal(False)
>>> result = True | s
>>> result.value
True
>>> s.value = True
>>> result.value
True

__xor__

__xor__(other: HasValue[N]) -> Computed[N]
__xor__(other: _ReactiveOf[Y]) -> Computed[R]
__xor__(
    other: _ReactiveOf[_SupportsRxor[T, R]],
) -> Computed[R]
__xor__(other: Y) -> Computed[R]
__xor__(other: _SupportsRxor[T, R]) -> Computed[R]
__xor__(other)

Return a reactive value for the bitwise XOR of self and other.

Parameters:

Name Type Description Default
other Any

The value to XOR with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value ^ other.value.

Example
>>> s = Signal(True)
>>> result = s ^ False
>>> result.value
True
>>> s.value = False
>>> result.value
False

__rxor__

__rxor__(other: HasValue[N]) -> Computed[N]
__rxor__(
    other: _ReactiveOf[_SupportsXor[T, R]],
) -> Computed[R]
__rxor__(other: _ReactiveOf[Y]) -> Computed[R]
__rxor__(other: _SupportsXor[T, R]) -> Computed[R]
__rxor__(other: Y) -> Computed[R]
__rxor__(other)

Return a reactive value for the bitwise XOR of self and other.

Parameters:

Name Type Description Default
other Any

The value to XOR with.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value ^ other.value.

Example
>>> s = Signal(True)
>>> result = False ^ s
>>> result.value
True
>>> s.value = False
>>> result.value
False

__lshift__

__lshift__(other: _ReactiveOf[Y]) -> Computed[R]
__lshift__(
    other: _ReactiveOf[_SupportsRlshift[T, R]],
) -> Computed[R]
__lshift__(other: Y) -> Computed[R]
__lshift__(other: _SupportsRlshift[T, R]) -> Computed[R]
__lshift__(other)

Return a reactive value for self left-shifted by other.

Parameters:

Name Type Description Default
other Any

The number of positions to shift.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value << other.value.

Example
>>> s = Signal(8)
>>> result = s << 2
>>> result.value
32
>>> s.value = 3
>>> result.value
12

__rlshift__

__rlshift__(
    other: _ReactiveOf[_SupportsLshift[T, R]],
) -> Computed[R]
__rlshift__(other: _ReactiveOf[Y]) -> Computed[R]
__rlshift__(other: _SupportsLshift[T, R]) -> Computed[R]
__rlshift__(other: Y) -> Computed[R]
__rlshift__(other)

Return a reactive value for other left-shifted by self.

Parameters:

Name Type Description Default
other Any

The value to shift.

required

Returns:

Type Description
Computed[Any]

A reactive value for other.value << self.value.

Example
>>> s = Signal(2)
>>> result = 1 << s
>>> result.value
4
>>> s.value = 5
>>> result.value
32

__rshift__

__rshift__(other: _ReactiveOf[Y]) -> Computed[R]
__rshift__(
    other: _ReactiveOf[_SupportsRrshift[T, R]],
) -> Computed[R]
__rshift__(other: Y) -> Computed[R]
__rshift__(other: _SupportsRrshift[T, R]) -> Computed[R]
__rshift__(other)

Return a reactive value for self right-shifted by other.

Parameters:

Name Type Description Default
other Any

The number of positions to shift.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value >> other.value.

Example
>>> s = Signal(32)
>>> result = s >> 2
>>> result.value
8
>>> s.value = 24
>>> result.value
6

__rrshift__

__rrshift__(
    other: _ReactiveOf[_SupportsRshift[T, R]],
) -> Computed[R]
__rrshift__(other: _ReactiveOf[Y]) -> Computed[R]
__rrshift__(other: _SupportsRshift[T, R]) -> Computed[R]
__rrshift__(other: Y) -> Computed[R]
__rrshift__(other)

Return a reactive value for other right-shifted by self.

Parameters:

Name Type Description Default
other Any

The value to shift.

required

Returns:

Type Description
Computed[Any]

A reactive value for other.value >> self.value.

Example
>>> s = Signal(2)
>>> result = 32 >> s
>>> result.value
8
>>> s.value = 4
>>> result.value
2

__divmod__

__divmod__(other: HasValue[N]) -> Computed[tuple[N, N]]
__divmod__(
    other: _FloatLike,
) -> Computed[tuple[float, float]]
__divmod__(other: _ReactiveOf[Y] | Y) -> Computed[R]
__divmod__(
    other: _ReactiveOf[_SupportsRdivmod[T, R]]
    | _SupportsRdivmod[T, R],
) -> Computed[R]
__divmod__(other)

Return a reactive value for the divmod of self and other.

Parameters:

Name Type Description Default
other Any

The value to use as the divisor.

required

Returns:

Type Description
Computed[Any]

A reactive value for divmod(self.value, other).

Example
>>> s = Signal(10)
>>> result = divmod(s, 3)
>>> result.value
(3, 1)
>>> s.value = 20
>>> result.value
(6, 2)

__rdivmod__

__rdivmod__(other: HasValue[N]) -> Computed[tuple[N, N]]
__rdivmod__(
    other: _FloatLike,
) -> Computed[tuple[float, float]]
__rdivmod__(
    other: _ReactiveOf[_SupportsDivmod[T, R]],
) -> Computed[R]
__rdivmod__(other: _ReactiveOf[Y]) -> Computed[R]
__rdivmod__(other: _SupportsDivmod[T, R]) -> Computed[R]
__rdivmod__(other: Y) -> Computed[R]
__rdivmod__(other)

Return a reactive value for the divmod of self and other.

Parameters:

Name Type Description Default
other Any

The value to use as the numerator.

required

Returns:

Type Description
Computed[Any]

A reactive value for divmod(other, self.value).

Example
>>> s = Signal(3)
>>> result = divmod(10, s)
>>> result.value
(3, 1)
>>> s.value = 4
>>> result.value
(2, 2)

__lt__

__lt__(other: _ReactiveOf[Y]) -> Computed[R]
__lt__(
    other: _ReactiveOf[_SupportsGt[T, R]],
) -> Computed[R]
__lt__(other: Y) -> Computed[R]
__lt__(other: _SupportsGt[T, R]) -> Computed[R]
__lt__(other)

Return a reactive value for whether self is less than other.

Parameters:

Name Type Description Default
other Any

The value to compare against.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value < other.

Example
>>> s = Signal(5)
>>> result = s < 10
>>> result.value
True
>>> s.value = 15
>>> result.value
False

__le__

__le__(other: _ReactiveOf[Y]) -> Computed[R]
__le__(
    other: _ReactiveOf[_SupportsGe[T, R]],
) -> Computed[R]
__le__(other: Y) -> Computed[R]
__le__(other: _SupportsGe[T, R]) -> Computed[R]
__le__(other)

Return a reactive value for whether self is less than or equal to other.

Parameters:

Name Type Description Default
other Any

The value to compare against.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value <= other.

Example
>>> s = Signal(5)
>>> result = s <= 5
>>> result.value
True
>>> s.value = 6
>>> result.value
False

__ge__

__ge__(other: _ReactiveOf[Y]) -> Computed[R]
__ge__(
    other: _ReactiveOf[_SupportsLe[T, R]],
) -> Computed[R]
__ge__(other: Y) -> Computed[R]
__ge__(other: _SupportsLe[T, R]) -> Computed[R]
__ge__(other)

Return a reactive value for whether self is greater than or equal to other.

Parameters:

Name Type Description Default
other Any

The value to compare against.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value >= other.

Example
>>> s = Signal(10)
>>> result = s >= 5
>>> result.value
True
>>> s.value = 3
>>> result.value
False

__gt__

__gt__(other: _ReactiveOf[Y]) -> Computed[R]
__gt__(
    other: _ReactiveOf[_SupportsLt[T, R]],
) -> Computed[R]
__gt__(other: Y) -> Computed[R]
__gt__(other: _SupportsLt[T, R]) -> Computed[R]
__gt__(other)

Return a reactive value for whether self is greater than other.

Parameters:

Name Type Description Default
other Any

The value to compare against.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value > other.

Example
>>> s = Signal(10)
>>> result = s > 5
>>> result.value
True
>>> s.value = 3
>>> result.value
False

__getitem__

__getitem__(key: HasValue[slice]) -> Computed[list[V]]
__getitem__(
    key: HasValue[slice],
) -> Computed[tuple[V, ...]]
__getitem__(key: HasValue[K]) -> Computed[V]
__getitem__(key: _ReactiveOf[K]) -> Computed[V]
__getitem__(key: K) -> Computed[V]
__getitem__(key)

Return a reactive value for the item or slice of self.

Parameters:

Name Type Description Default
key Any

The index or slice to retrieve.

required

Returns:

Type Description
Computed[Any]

A reactive value for self.value[key].

Example
>>> s = Signal([1, 2, 3, 4, 5])
>>> result = s[2]
>>> result.value
3
>>> s.value = [10, 20, 30, 40, 50]
>>> result.value
30

Functions

signified.computed

computed(func)

Make a function return a Computed that follows its arguments.

Each time the result is calculated, every Signal, Computed, or Binding argument is replaced by its current value, so func receives plain values. Other arguments are passed as-is, including lists or dictionaries that hold reactive values; call deep_unref inside func to read those.

The result recalculates when a reactive value it read changes, including reads made inside func.

Parameters:

Name Type Description Default
func Callable[..., R]

Function that computes a derived value from its inputs.

required

Returns:

Type Description
Callable[..., Computed[R]]

A wrapper that returns a Computed when called.

signified.effect

effect(func)

Make a function start an Effect each time it is called.

Arguments are handled as in computed: each Signal, Computed, or Binding argument is replaced by its current value, and other arguments are passed as-is.

The effect runs immediately, or when the enclosing batch exits, and again whenever a reactive value it read changes. Keep the returned Effect for as long as it should run.

Parameters:

Name Type Description Default
func Callable[..., None]

Function run for its side effects.

required

Returns:

Type Description
Callable[..., Effect]

A wrapper that returns an Effect when called.

Example
>>> seen = []
>>> s = Signal(1)

>>> @effect
... def log(x):
...     seen.append(x)

>>> e = log(s)
>>> seen
[1]
>>> s.value = 2
>>> seen
[1, 2]
>>> e.dispose()
>>> s.value = 3
>>> seen
[1, 2]

signified.unref

unref(value: HasValue[T]) -> T
unref(value: HasValue[T] | HasValue[U]) -> T | U
unref(value)

Unwrap exactly one reactive boundary.

When called inside a Computed or Effect evaluation, the reactive registers as a dependency — equivalent to reading .value directly.

Parameters:

Name Type Description Default
value Any

Plain value or reactive value.

required

Returns:

Type Description
Any

The value inside one reactive wrapper, or the original plain value.

Example
source = Signal(5)
unref(source)  # 5

signified.has_value

has_value(obj, type_)

Check whether an object's resolved value is an instance of type_.

A typed guard around unref. Useful when a parameter accepts either a plain value or a reactive wrapper and you need to narrow the type.

Parameters:

Name Type Description Default
obj Any

Value to inspect. May be plain or reactive.

required
type_ type[T]

Expected resolved value type.

required

Returns:

Type Description
TypeGuard[HasValue[T]]

True if unref(obj) is an instance of type_; otherwise False.

Example
>>> candidate = Signal(42)
>>> has_value(candidate, int)
True
>>> has_value(candidate, str)
False

signified.is_reactive

is_reactive(
    obj: HasValue[T],
) -> TypeGuard[ReactiveValue[T]]
is_reactive(
    obj: HasValue[T] | HasValue[U],
) -> TypeGuard[ReactiveValue[T] | ReactiveValue[U]]
is_reactive(obj)

Return whether an object is a signified reactive wrapper.

This guard narrows a plain-or-reactive HasValue to ReactiveValue in the true branch without reading the wrapped value or creating a dependency.

Parameters:

Name Type Description Default
obj object

Value to inspect.

required

Returns:

Type Description
bool

True for a Signal, Computed,

bool

or Binding.

signified.as_rx

as_rx(val: Binding[T]) -> Binding[T]
as_rx(val: Computed[T]) -> Computed[T]
as_rx(val: Signal[T]) -> Signal[T]
as_rx(val: HasValue[T]) -> ReactiveValue[T]
as_rx(
    val: HasValue[T] | HasValue[U],
) -> ReactiveValue[T] | ReactiveValue[U]
as_rx(val)

Normalize a value to a reactive object.

If val is already reactive, it is returned unchanged. Otherwise a new Signal is created wrapping the value.

Parameters:

Name Type Description Default
val Any

Plain value or reactive value.

required

Returns:

Type Description
ReactiveValue[Any]

A reactive value.

signified.batch

batch()

Defer effects until the outermost synchronous batch exits.

Writes are immediate and computed reads remain current. Newly created effects are deferred too. Nested batches combine; cascading writes may run an effect more than once. This is not a transaction: errors do not roll back writes, and ordinary reads can see intermediate state. A batch defers only work queued on the thread that entered it. Do not span await.

One failing effect raises its exception directly; several are raised as an ExceptionGroup. A body exception alone is re-raised unchanged; simultaneous body and flush failures are grouped together.

signified.untracked

untracked()

Read without subscribing the enclosing computation or effect.

Nested computations still collect their own dependencies. Reads return current values and retain normal hooks and errors. Applies only to the thread that enters it; this context must not span await.

signified.sample

sample(value, signal, at)

Return a Computed holding value as if signal held at.

Reading the result gives what reading value inside with signal.at(at): would give, without changing signal or any cached value. at may be reactive; it is read with signal's real value, then substituted.

The result recalculates when at changes, or when something value read other than signal changes. Changing only signal leaves it cached. Values that do not depend on signal are read as they are; values that do are calculated again for at, and the result keeps them.

Those values are calculated as on a first read, so a computed's custom equal has no earlier value to keep. Where Signal.at() would keep a cached value because equal accepts the new one, sample gives the new one, which that equal calls equal to it. This also means the result does not depend on what the live graph cached when it was read.

A Computed cannot change signals, including with Signal.at; use sample to read a value at another value of a signal.

Parameters:

Name Type Description Default
value HasValue[T]

The value to read.

required
signal Signal[S]

The Signal to give another value.

required
at HasValue[S]

The value signal holds while value is read.

required

Returns:

Type Description
Computed[T]

A Computed of value as if signal held at.

Raises:

Type Description
TypeError

If signal is not a Signal.

Example
>>> frame = Signal(0)
>>> position = computed(lambda f: f * 10)(frame)
>>> held = sample(position, frame, 3)
>>> until = sample(position, frame, computed(lambda f: min(f, 3))(frame))
>>> frame.value = 2
>>> held.value, until.value
(30, 20)
>>> frame.value = 5
>>> held.value, until.value, position.value
(30, 30, 50)

signified.tracked_fields

tracked_fields(cls: C) -> C
tracked_fields(*names: str) -> Callable[[C], C]
tracked_fields(*args)

Track reads and reassignment of a class's attributes.

Reading a tracked attribute returns exactly what was stored: a plain value, or the Signal, Computed, or Binding that was assigned. It never unwraps. Inside a computation or effect, the read also depends on the attribute itself, so assigning a new value invalidates the reader. Use unref as usual to read through a stored reactive value.

Assignment uses the usual change rule: built-in scalars compare by value, other objects by identity. Assigning a reactive value replaces the stored one; it never writes into the previously stored signal.

Apply it above @dataclass to track every field, or pass names to track only those. Names are required for a class that is not a dataclass. Both slotted and dict-based classes work; frozen dataclasses are rejected. Copies and pickles store plain values and get their own tracking.

Reads outside a computation skip the graph, but still cost a descriptor call. In-place mutation of a stored object is not observed.

Example
>>> from dataclasses import dataclass
>>> from signified import HasValue, unref
>>> @tracked_fields
... @dataclass(slots=True)
... class Material:
...     roughness: HasValue[float] = 0.5
>>> material = Material()
>>> doubled = Computed(lambda: unref(material.roughness) * 2)
>>> doubled.value
1.0
>>> material.roughness = 0.25
>>> doubled.value
0.5
>>> material.roughness = Signal(0.1)
>>> doubled.value
0.2

Nested values

signified.deep_unref module-attribute

deep_unref

Replace reactive values inside nested containers with their current values.

For example, deep_unref({"x": Signal(1)}) returns {"x": 1}. Lists, tuples, dictionaries (keys and values), sets, frozensets, deques, and NumPy object arrays are rebuilt with their reactive contents replaced. Other objects are returned unchanged.

To support your own type, register a handler with @deep_unref.register(MyType). The handler receives the object and a resolve function (ResolveContext); call resolve on each field to read and return the rebuilt object. Only that exact type uses the handler, and registering the type again replaces it.

Called inside a computation or effect, every reactive value it reads becomes a dependency. Repeated references are resolved separately, cycles eventually raise RecursionError, and keys or set members that collide after resolving raise ValueError.

signified.ResolveContext

Resolve a child within the current traversal.

Handlers call resolve(child) for each field they want to visit. The supplied context recursively resolves values with the current handlers.

Resolving nested values has examples of custom handlers.

Types

HasValue

HasValue[T] is T | Computed[T] | Signal[T] | Binding[T]: a plain or reactive value that resolves to T. Use it to annotate a parameter that accepts either.

ReactiveValue

ReactiveValue[T] is Computed[T] | Signal[T] | Binding[T]: a reactive value that resolves to T.