Skip to content

Option

Bases: Pipeable

Type Option[T] represents an optional value.

Every Option is either:

  • Some and contains a value
  • None, and does not.

This is a common type in Rust, and is used to represent values that may be absent.

In python, this is best tought of a an union type T | None, but with additional methods to operate on the contained value in a functional style.

Option[T] and/or T | None types are very useful, as they have a number of uses:

  • Initial values
  • Union types
  • Return value where None is returned on error
  • Optional class fields
  • Optional function arguments

The fact that T | None is a very common pattern in python, but without a dedicated structure/handling, leads to:

  • a lot of boilerplate code
  • potential bugs (even with type checkers)
  • less readable code (where does the None come from? is it expected?).

Option[T] instances are commonly paired with pattern matching. This allow to query the presence of a value and take action, always accounting for the None case.

__bool__()

Prevent implicit Some|None value checking in boolean contexts.

Raises:

Type Description
TypeError

Always, to prevent implicit Some|None value checking.

Example:

>>> import pyochain as pc
>>> x = pc.Some(42)
>>> bool(x)
Traceback (most recent call last):
...
TypeError: Option instances cannot be used in boolean contexts for implicit `Some|None` value checking. Use is_some() or is_none() instead.

__eq__(other)

Checks if this Option and other are equal.

A plain Python None is considered equal to a pyochain.NoneOption instance.

A plain value of type T is considered equal to a pyochain.Some[T] instance.

Parameters:

Name Type Description Default
other object

The other object to compare with.

required

Returns:

Name Type Description
bool bool

True if both instances are equal, False otherwise.

See Also
  • Option.eq for a type-safe, performant version that only accepts Option[T] instances.

Example:

>>> import pyochain as pc
>>> pc.Some(42) == pc.Some(42)
True
>>> pc.Some(42) == pc.Some(21)
False
>>> pc.Some(42) == pc.NONE
False
>>> pc.NONE == pc.NONE
True
>>> pc.NONE == None
True
>>> pc.Some(42) == 42
True

__new__(value)

Creates an Option[V] from a value that may be None.

When calling Option(value), this method automatically redirects to: - Some(value) if the value is not None - NONE if the value is None

Parameters:

Name Type Description Default
value V | None

The value to convert into an Option[V].

required

Returns:

Type Description
Option[V]

Option[V]: Some(value) if the value is not None, otherwise NONE.

Example:

>>> import pyochain as pc
>>> pc.Option(42)
Some(42)
>>> pc.Option(None)
NONE

and_(optb)

Returns NONE if the option is NONE, otherwise returns optb.

This is similar to and_then, except that the value is passed directly instead of through a closure.

Parameters:

Name Type Description Default
optb Option[U]

The option to return if the original option is NONE

required

Returns: Option[U]: NONE if the original option is NONE, otherwise optb.

Example:

>>> import pyochain as pc
>>> pc.Some(2).and_(pc.NONE)
NONE
>>> pc.NONE.and_(pc.Some("foo"))
NONE
>>> pc.Some(2).and_(pc.Some("foo"))
Some('foo')
>>> pc.NONE.and_(pc.NONE)
NONE

and_then(f, *args, **kwargs)

Calls a function if the option is Some, otherwise returns None.

Parameters:

Name Type Description Default
f Callable[Concatenate[T, P], Option[R]]

The function to call with the Some value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Type Description
Option[R]

Option[R]: The result of the function if Some, otherwise None.

Example:

>>> import pyochain as pc
>>> def sq(x: int) -> Option[int]:
...     return pc.Some(x * x)
>>> def nope(x: int) -> Option[int]:
...     return pc.NONE
>>> pc.Some(2).and_then(sq).and_then(sq)
Some(16)
>>> pc.Some(2).and_then(sq).and_then(nope)
NONE
>>> pc.Some(2).and_then(nope).and_then(sq)
NONE
>>> pc.NONE.and_then(sq).and_then(sq)
NONE

and_then_star(func)

and_then_star(
    func: Callable[[Any], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4, T5], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4, T5, T6], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7], Option[R]],
) -> Option[R]
and_then_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8], Option[R]
    ],
) -> Option[R]
and_then_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8, T9], Option[R]
    ],
) -> Option[R]
and_then_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], Option[R]
    ],
) -> Option[R]

Calls a function if the option is Some, unpacking the iterable into the function.

Parameters:

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

The function to call with the unpacked Some value.

required

Returns:

Type Description
Option[R]

Option[R]: The result of the function if Some, otherwise None.

Example:

>>> import pyochain as pc
>>> pc.Some((2, 3)).and_then_star(lambda x, y: pc.Some(x + y))
Some(5)
>>> pc.NONE.and_then_star(lambda x, y: pc.Some(x + y))
NONE

eq(other)

Checks if two Option[T] instances are equal.

Note

This method behave similarly to __eq__, but only accepts Option[T] instances as argument.

This avoids runtime isinstance checks (we check for boolean is_some(), which is a simple function call), and is more type-safe.

Parameters:

Name Type Description Default
other Option[T]

The other Option[T] instance to compare with.

required

Returns:

Name Type Description
bool bool

True if both instances are equal, False otherwise.

Example:

>>> import pyochain as pc
>>> pc.Some(42).eq(pc.Some(42))
True
>>> pc.Some(42).eq(pc.Some(21))
False
>>> pc.Some(42).eq(pc.NONE)
False
>>> pc.NONE.eq(pc.NONE)
True

expect(msg)

Returns the contained Some value.

Raises an exception with a provided message if the value is None.

Parameters:

Name Type Description Default
msg str

The message to include in the exception if the result is None.

required

Returns:

Name Type Description
T T

The contained Some value.

Raises:

Type Description
OptionUnwrapError

If the result is None.

Example:

>>> import pyochain as pc
>>> pc.Some("value").expect("fruits are healthy")
'value'
>>> pc.NONE.expect("fruits are healthy")
Traceback (most recent call last):
...
OptionUnwrapError: fruits are healthy (called `expect` on a `None`)

filter(predicate, *args, **kwargs)

Returns None if the option is None, otherwise calls predicate with the wrapped value.

This function works similar to Iter.filter in the sense that we only keep the value if it matches a predicate.

You can imagine the Option[T] being an iterator over one or zero elements.

Parameters:

Name Type Description Default
predicate Callable[Concatenate[T, P], R]

The predicate to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to predicate.

()
**kwargs P.kwargs

Additional keyword arguments to pass to predicate.

{}

Returns:

Type Description
Option[T]

Option[T]: Some[T] if predicate returns true (where T is the wrapped value), NONE if predicate returns false.

Example:

>>> import pyochain as pc
>>>
>>> def is_even(n: int) -> bool:
...     return n % 2 == 0
>>>
>>> pc.NONE.filter(is_even)
NONE
>>> pc.Some(3).filter(is_even)
NONE
>>> pc.Some(4).filter(is_even)
Some(4)

flatten()

Flattens a nested Option.

Converts an Option[Option[U]] into an Option[U] by removing one level of nesting.

Equivalent to Option.and_then(lambda x: x).

Returns:

Type Description
Option[U]

Option[U]: The flattened option.

Example:

>>> import pyochain as pc
>>> pc.Some(pc.Some(42)).flatten()
Some(42)
>>> pc.Some(pc.NONE).flatten()
NONE
>>> pc.NONE.flatten()
NONE

if_some(value) staticmethod

Creates an Option[V] based on the truthiness of a value.

Parameters:

Name Type Description Default
value V

The value to evaluate.

required

Returns:

Type Description
Option[V]

Option[V]: Some(value) if the value is truthy, otherwise NONE.

Example:

>>> import pyochain as pc
>>> pc.Option.if_some(42)
Some(42)
>>> pc.Option.if_some(0)
NONE
>>> pc.Option.if_some("hello")
Some('hello')
>>> pc.Option.if_some("")
NONE

if_true(value, *, predicate) staticmethod

Creates an Option[V] based on a predicate condition on the provided value.

Parameters:

Name Type Description Default
value V

The value to wrap in Some if the condition is True.

required
predicate Callable[[V], bool]

The condition to evaluate.

required

Returns:

Type Description
Option[V]

Option[V]: Some(value) if the condition is True, otherwise NONE.

Example:

>>> import pyochain as pc
>>> pc.Option.if_true(42, predicate=lambda x: x == 42)
Some(42)
>>> pc.Option.if_true(21, predicate=lambda x: x == 42)
NONE
>>> from pathlib import Path
>>> pc.Option.if_true(Path("README.md"), predicate=Path.exists).map(str)
Some('README.md')
>>> pc.Option.if_true(Path("README.md"), predicate=lambda p: p.exists()).map(str) # Same as above
Some('README.md')

inspect(f, *args, **kwargs)

Applies a function to the contained Some value, returning the original Option.

This allows side effects (logging, debugging, metrics, etc.) on the wrapped value without changing it.

Parameters:

Name Type Description Default
f Callable[Concatenate[T, P], object]

Function to apply to the Some value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Type Description
Option[T]

Option[T]: The original option, unchanged.

Example:

>>> import pyochain as pc
>>> seen: list[int] = []
>>> pc.Some(2).inspect(lambda x: seen.append(x))
Some(2)
>>> seen
[2]
>>> pc.NONE.inspect(lambda x: seen.append(x))
NONE
>>> seen
[2]

is_none()

Returns True if the option is a None value.

Returns:

Name Type Description
bool bool

True if the option is a _None variant, False otherwise.

Example:

>>> import pyochain as pc
>>> x: Option[int] = pc.Some(2)
>>> x.is_none()
False
>>> y: Option[int] = pc.NONE
>>> y.is_none()
True

is_none_or(func, *args, **kwargs)

Returns true if the option is a None or the value inside of it matches a predicate.

Parameters:

Name Type Description Default
func Callable[Concatenate[T, P], bool]

The predicate to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to func.

()
**kwargs P.kwargs

Additional keyword arguments to pass to func.

{}

Returns:

Name Type Description
bool bool

True if the option is None or the predicate returns True for the contained value, False otherwise.

Example:

>>> import pyochain as pc
>>> pc.Some(2).is_none_or(lambda x: x > 1)
True
>>> pc.Some(0).is_none_or(lambda x: x > 1)
False
>>> pc.NONE.is_none_or(lambda x: x > 1)
True
>>> pc.Some("hello").is_none_or(lambda x: len(x) > 1)
True

is_some()

Returns True if the option is a Some value.

Returns:

Name Type Description
bool bool

True if the option is a Some variant, False otherwise.

Example:

>>> import pyochain as pc
>>> x: Option[int] = pc.Some(2)
>>> x.is_some()
True
>>> y: Option[int] = pc.NONE
>>> y.is_some()
False

is_some_and(predicate, *args, **kwargs)

Returns true if the option is a Some and the value inside of it matches a predicate.

Parameters:

Name Type Description Default
predicate Callable[Concatenate[T, P], bool]

The predicate to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to predicate.

()
**kwargs P.kwargs

Additional keyword arguments to pass to predicate.

{}

Returns:

Name Type Description
bool bool

True if the option is Some and the predicate returns True for the contained value, False otherwise.

Example:

>>> import pyochain as pc
>>> x = pc.Some(2)
>>> x.is_some_and(lambda x: x > 1)
True

>>> x = pc.Some(0)
>>> x.is_some_and(lambda x: x > 1)
False
>>> x = pc.NONE
>>> x.is_some_and(lambda x: x > 1)
False
>>> x = pc.Some("hello")
>>> x.is_some_and(lambda x: len(x) > 1)
True

iter()

Creates an Iter over the optional value.

  • If the option is Some(value), the iterator yields value.
  • If the option is NONE, the iterator yields nothing.

Equivalent to Iter((self,)).

Returns:

Type Description
Iter[T]

Iter[T]: An iterator over the optional value.

Example:

>>> import pyochain as pc
>>> pc.Some(42).iter().next()
Some(42)
>>> pc.NONE.iter().next()
NONE

map(f, *args, **kwargs)

Maps an Option[T] to Option[U].

Done by applying a function to a contained Some value, leaving a None value untouched.

Parameters:

Name Type Description Default
f Callable[Concatenate[T, P], R]

The function to apply to the Some value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Type Description
Option[R]

Option[R]: A new Option with the mapped value if Some, otherwise None.

Example:

>>> import pyochain as pc
>>> pc.Some("Hello, World!").map(len)
Some(13)
>>> pc.NONE.map(len)
NONE

map_or(default, f, *args, **kwargs)

Returns the result of applying a function to the contained value if Some, otherwise returns the default value.

Parameters:

Name Type Description Default
default R

The default value to return if NONE.

required
f Callable[Concatenate[T, P], R]

The function to apply to the contained value.

required
*args P.args

Additional positional arguments to pass to f.

()
**kwargs P.kwargs

Additional keyword arguments to pass to f.

{}

Returns:

Name Type Description
R R

The result of f(self.unwrap()) if Some, otherwise default.

Example:

>>> import pyochain as pc
>>> pc.Some(2).map_or(0, lambda x: x * 10)
20
>>> pc.NONE.map_or(0, lambda x: x * 10)
0

map_or_else(default, f)

Returns the result of applying a function to the contained value if Some, otherwise computes a default value.

Parameters:

Name Type Description Default
default Callable[[], R]

A function returning the default value if NONE.

required
f Callable[[T], R]

The function to apply to the contained value.

required

Returns:

Name Type Description
R R

The result of f(self.unwrap()) if Some, otherwise default().

Example:

>>> import pyochain as pc
>>> pc.Some(2).map_or_else(lambda: 0, lambda x: x * 10)
20
>>> pc.NONE.map_or_else(lambda: 0, lambda x: x * 10)
0

map_star(func)

map_star(func: Callable[[Any], R]) -> Option[R]
map_star(func: Callable[[T1, T2], R]) -> Option[R]
map_star(func: Callable[[T1, T2, T3], R]) -> Option[R]
map_star(func: Callable[[T1, T2, T3, T4], R]) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7, T8], R],
) -> Option[R]
map_star(
    func: Callable[[T1, T2, T3, T4, T5, T6, T7, T8, T9], R],
) -> Option[R]
map_star(
    func: Callable[
        [T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], R
    ],
) -> Option[R]

Maps an Option[Iterable] to Option[U] by unpacking the iterable into the function.

Done by applying a function to a contained Some value, leaving a None value untouched.

Parameters:

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

The function to apply to the unpacked Some value.

required

Returns:

Type Description
Option[R]

Option[R]: A new Option with the mapped value if Some, otherwise None.

Example:

>>> import pyochain as pc
>>> pc.Some((2, 3)).map_star(lambda x, y: x + y)
Some(5)
>>> pc.NONE.map_star(lambda x, y: x + y)
NONE

ne(other)

Checks if two Option[T] instances are not equal.

Parameters:

Name Type Description Default
other Option[T]

The other Option[T] instance to compare with.

required

Returns:

Name Type Description
bool bool

True if both instances are not equal, False otherwise.

Example:

>>> import pyochain as pc
>>> pc.Some(42).ne(pc.Some(21))
True
>>> pc.Some(42).ne(pc.Some(42))
False
>>> pc.Some(42).ne(pc.NONE)
True
>>> pc.NONE.ne(pc.NONE)
False

ok_or(err)

Converts the option to a Result.

Parameters:

Name Type Description Default
err E

The error value to use if the option is NONE.

required

Returns:

Type Description
Result[T, E]

Result[T, E]: Ok(v) if Some(v), otherwise Err(err).

Example:

>>> import pyochain as pc
>>> pc.Some(1).ok_or('fail')
Ok(1)
>>> pc.NONE.ok_or('fail')
Err('fail')

ok_or_else(err)

Converts the option to a Result.

Parameters:

Name Type Description Default
err Callable[[], E]

A function returning the error value if the option is NONE.

required

Returns:

Type Description
Result[T, E]

Result[T, E]: Ok(v) if Some(v), otherwise Err(err()).

Example:

>>> import pyochain as pc
>>> pc.Some(1).ok_or_else(lambda: 'fail')
Ok(1)
>>> pc.NONE.ok_or_else(lambda: 'fail')
Err('fail')

or_(optb)

Returns the option if it contains a value, otherwise returns optb.

Parameters:

Name Type Description Default
optb Option[T]

The option to return if the original option is NONE.

required

Returns:

Type Description
Option[T]

Option[T]: The original option if it is Some, otherwise optb.

Example:

>>> import pyochain as pc
>>> pc.Some(2).or_(pc.NONE)
Some(2)
>>> pc.NONE.or_(pc.Some(100))
Some(100)
>>> pc.Some(2).or_(pc.Some(100))
Some(2)
>>> pc.NONE.or_(pc.NONE)
NONE

or_else(f)

Returns the Option[T] if it contains a value, otherwise calls a function and returns the result.

Parameters:

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

The function to call if the option is None.

required

Returns:

Type Description
Option[T]

Option[T]: The original Option if it is Some, otherwise the result of the function.

Example:

>>> import pyochain as pc
>>> def nobody() -> Option[str]:
...     return pc.NONE
>>> def vikings() -> Option[str]:
...     return pc.Some("vikings")
>>> pc.Some("barbarians").or_else(vikings)
Some('barbarians')
>>> pc.NONE.or_else(vikings)
Some('vikings')
>>> pc.NONE.or_else(nobody)
NONE

reduce(other, func)

Reduces two options into one, using the provided function if both are Some.

If self is Some(s) and other is Some(o), this method returns Some(func(s, o)).

Otherwise, if only one of self and other is Some, that value is returned.

If both self and other are NONE, NONE is returned.

Parameters:

Name Type Description Default
other Option[T]

The second option.

required
func Callable[[T, T], T]

The function to apply to the unwrapped values.

required

Returns:

Type Description
Option[T]

Option[T]: The resulting option after reduction.

Example:

>>> import pyochain as pc
>>> s12 = pc.Some(12)
>>> s17 = pc.Some(17)
>>>
>>> def add(a: int, b: int) -> int:
...     return a + b
>>>
>>> s12.reduce(s17, add)
Some(29)
>>> s12.reduce(pc.NONE, add)
Some(12)
>>> pc.NONE.reduce(s17, add)
Some(17)
>>> pc.NONE.reduce(pc.NONE, add)
NONE

transpose()

Transposes an Option of a Result into a Result of an Option.

Some(Ok[T]) is mapped to Ok(Some[T]), Some(Err[E]) is mapped to Err[E], and NONE will be mapped to Ok(NONE).

Returns:

Type Description
Result[Option[T], E]

Result[Option[T], E]: The transposed result.

Example:

>>> import pyochain as pc
>>> pc.Some(pc.Ok(5)).transpose()
Ok(Some(5))
>>> pc.NONE.transpose()
Ok(NONE)
>>> pc.Some(pc.Err("error")).transpose()
Err('error')

unwrap()

Returns the contained Some value.

Returns:

Name Type Description
T T

The contained Some value.

Raises:

Type Description
OptionUnwrapError

If the option is None.

Example:

>>> import pyochain as pc
>>> pc.Some("car").unwrap()
'car'
>>> import pyochain as pc
>>> pc.NONE.unwrap()
Traceback (most recent call last):
...
OptionUnwrapError: called `unwrap` on a `None`

unwrap_or(default)

Returns the contained Some value or a provided default.

Parameters:

Name Type Description Default
default T

The value to return if the result is None.

required

Returns:

Name Type Description
T T

The contained Some value or the provided default.

Example:

>>> import pyochain as pc
>>> pc.Some("car").unwrap_or("bike")
'car'
>>> pc.NONE.unwrap_or("bike")
'bike'

unwrap_or_else(f)

Returns the contained Some value or computes it from a function.

Parameters:

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

A function that returns a default value if the result is None.

required

Returns:

Name Type Description
T T

The contained Some value or the result of the function.

Example:

>>> import pyochain as pc
>>> k = 10
>>> pc.Some(4).unwrap_or_else(lambda: 2 * k)
4
>>> pc.NONE.unwrap_or_else(lambda: 2 * k)
20

unzip()

Unzips an Option of a tuple into a tuple of Options.

If the option is Some((a, b)), this method returns (Some(a), Some(b)). If the option is NONE, it returns (NONE, NONE).

Returns:

Type Description
tuple[Option[T], Option[U]]

tuple[Option[T], Option[U]]: A tuple containing two options.

Example:

>>> import pyochain as pc
>>> pc.Some((1, 'a')).unzip()
(Some(1), Some('a'))
>>> pc.NONE.unzip()
(NONE, NONE)

xor(optb)

Returns Some if exactly one of self, optb is Some, otherwise returns NONE.

Parameters:

Name Type Description Default
optb Option[T]

The other option to compare with.

required

Returns:

Type Description
Option[T]

Option[T]: Some value if exactly one option is Some, otherwise NONE.

Example:

>>> import pyochain as pc
>>> pc.Some(2).xor(pc.NONE)
Some(2)
>>> pc.NONE.xor(pc.Some(2))
Some(2)
>>> pc.Some(2).xor(pc.Some(2))
NONE
>>> pc.NONE.xor(pc.NONE)
NONE

zip(other)

Returns an Option[tuple[T, U]] containing a tuple of the values if both options are Some, otherwise returns NONE.

Parameters:

Name Type Description Default
other Option[U]

The other option to zip with.

required

Returns:

Type Description
Option[tuple[T, U]]

Option[tuple[T, U]]: Some((self, other)) if both are Some, otherwise NONE.

Example:

>>> import pyochain as pc
>>> pc.Some(1).zip(pc.Some('a'))
Some((1, 'a'))
>>> pc.Some(1).zip(pc.NONE)
NONE
>>> pc.NONE.zip(pc.Some('a'))
NONE

zip_with(other, f)

Zips self and another Option with function f.

If self is Some(s) and other is Some(o), this method returns Some(f(s, o)).

Otherwise, NONE is returned.

Parameters:

Name Type Description Default
other Option[U]

The second option.

required
f Callable[[T, U], R]

The function to apply to the unwrapped values.

required

Returns:

Type Description
Option[R]

Option[R]: The resulting option after applying the function.

Example:

>>> from dataclasses import dataclass
>>> import pyochain as pc
>>>
>>> @dataclass
... class Point:
...     x: float
...     y: float
>>>
>>> x = pc.Some(17.5)
>>> y = pc.Some(42.7)
>>> x.zip_with(y, Point)
Some(Point(x=17.5, y=42.7))
>>> x.zip_with(pc.NONE, Point)
NONE
>>> pc.NONE.zip_with(y, Point)
NONE