OptionType
Bases: Pipeable
OptionType is the common interface for an optional value.
Option[T] is the union of Some[T] and Null[T], and represents a value that can only have two states:
Some(value)Null().
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.
Example:
>>> from pyochain import Option, Some, Null
>>> def divide(a: int, b: int) -> Option[int]:
... if b == 0:
... return Null()
... return Some(a // b)
>>>
>>> divide(10, 2)
Some(5)
>>> divide(10, 0)
NONE
__bool__()
Prevent implicit Some|None value checking in boolean contexts.
Raises:
| Type | Description |
|---|---|
TypeError
|
Always, to prevent implicit |
Example:
>>> from pyochain import Some
>>> x = 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.Null instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
object
|
The other object to compare with. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
See Also
Option.eqfor a type-safe, performant version that only acceptsOption[T]instances.
Example:
>>> from pyochain import Some, NONE
>>> Some(42) == Some(42)
True
>>> Some(42) == Some(21)
False
>>> Some(42) == NONE
False
>>> NONE == NONE
True
>>> NONE == None
True
>>> Some(42) == 42
False
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 |
required |
Returns:
Option[U]: NONE if the original option is NONE, otherwise optb.
Example:
>>> from pyochain import Some, NONE
>>> Some(2).and_(NONE)
NONE
>>> NONE.and_(Some("foo"))
NONE
>>> Some(2).and_(Some("foo"))
Some('foo')
>>> NONE.and_(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 |
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 |
Example:
>>> from pyochain import Some, NONE
>>> def sq(x: int) -> Option[int]:
... return Some(x * x)
>>> def nope(x: int) -> Option[int]:
... return NONE
>>> Some(2).and_then(sq).and_then(sq)
Some(16)
>>> Some(2).and_then(sq).and_then(nope)
NONE
>>> Some(2).and_then(nope).and_then(sq)
NONE
>>> 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 |
required |
Returns:
| Type | Description |
|---|---|
Option[R]
|
Option[R]: The result of the function if |
Example:
>>> from pyochain import Some, NONE
>>> Some((2, 3)).and_then_star(lambda x, y: Some(x + y))
Some(5)
>>> NONE.and_then_star(lambda x, y: 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 |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
Example:
>>> from pyochain import Some, NONE
>>> Some(42).eq(Some(42))
True
>>> Some(42).eq(Some(21))
False
>>> Some(42).eq(NONE)
False
>>> NONE.eq(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 |
required |
Returns:
| Name | Type | Description |
|---|---|---|
T |
T
|
The contained |
Raises:
| Type | Description |
|---|---|
OptionUnwrapError
|
If the result is |
Example:
>>> from pyochain import Some, NONE
>>> Some("value").expect("fruits are healthy")
'value'
>>> 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]: |
Example:
>>> from pyochain import Some, NONE
>>>
>>> def is_even(n: int) -> bool:
... return n % 2 == 0
>>>
>>> NONE.filter(is_even)
NONE
>>> Some(3).filter(is_even)
NONE
>>> 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:
>>> from pyochain import Some, NONE
>>> Some(Some(42)).flatten()
Some(42)
>>> Some(NONE).flatten()
NONE
>>> NONE.flatten()
NONE
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 |
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:
>>> from pyochain import Some, NONE, Vec
>>> seen = Vec[int](())
>>> Some(2).inspect(lambda x: seen.append(x))
Some(2)
>>> seen
Vec(2)
>>> NONE.inspect(lambda x: seen.append(x))
NONE
>>> seen
Vec(2)
is_none()
Returns True if the option is a None value.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
Example:
>>> from pyochain import Some, NONE
>>> x: Option[int] = Some(2)
>>> x.is_none()
False
>>> y: Option[int] = 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
|
|
Example:
>>> from pyochain import Some, NONE
>>> Some(2).is_none_or(lambda x: x > 1)
True
>>> Some(0).is_none_or(lambda x: x > 1)
False
>>> NONE.is_none_or(lambda x: x > 1)
True
>>> 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
|
|
Example:
>>> from pyochain import Some, NONE
>>> x: Option[int] = Some(2)
>>> x.is_some()
True
>>> y: Option[int] = 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
|
|
Example:
>>> from pyochain import Some, NONE
>>> x = Some(2)
>>> x.is_some_and(lambda x: x > 1)
True
>>> x = Some(0)
>>> x.is_some_and(lambda x: x > 1)
False
>>> x = NONE
>>> x.is_some_and(lambda x: x > 1)
False
>>> x = 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 yieldsvalue. - 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:
>>> from pyochain import Some, NONE
>>> Some(42).iter().next()
Some(42)
>>> 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 |
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 |
Example:
>>> from pyochain import Some, NONE
>>> Some("Hello, World!").map(len)
Some(13)
>>> 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:
>>> from pyochain import Some, NONE
>>> Some(2).map_or(0, lambda x: x * 10)
20
>>> 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:
>>> from pyochain import Some, NONE
>>> Some(2).map_or_else(lambda: 0, lambda x: x * 10)
20
>>> 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 |
required |
Returns:
| Type | Description |
|---|---|
Option[R]
|
Option[R]: A new |
Example:
>>> from pyochain import Some, NONE
>>> Some((2, 3)).map_star(lambda x, y: x + y)
Some(5)
>>> 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 |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
|
Example:
>>> from pyochain import Some, NONE
>>> Some(42).ne(Some(21))
True
>>> Some(42).ne(Some(42))
False
>>> Some(42).ne(NONE)
True
>>> NONE.ne(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 |
required |
Returns:
| Type | Description |
|---|---|
Result[T, E]
|
Result[T, E]: |
Example:
>>> from pyochain import Some, NONE
>>> Some(1).ok_or("fail")
Ok(1)
>>> 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:
>>> from pyochain import Some, NONE
>>> Some(1).ok_or_else(lambda: "fail")
Ok(1)
>>> 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 |
required |
Returns:
| Type | Description |
|---|---|
Option[T]
|
Option[T]: The original option if it is |
Example:
>>> from pyochain import Some, NONE
>>> Some(2).or_(NONE)
Some(2)
>>> NONE.or_(Some(100))
Some(100)
>>> Some(2).or_(Some(100))
Some(2)
>>> NONE.or_(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 |
required |
Returns:
| Type | Description |
|---|---|
Option[T]
|
Option[T]: The original |
Example:
>>> from pyochain import Some, NONE
>>> def nobody() -> Option[str]:
... return NONE
>>> def vikings() -> Option[str]:
... return Some("vikings")
>>> Some("barbarians").or_else(vikings)
Some('barbarians')
>>> NONE.or_else(vikings)
Some('vikings')
>>> 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:
>>> from pyochain import Some, NONE
>>> s12 = Some(12)
>>> s17 = Some(17)
>>>
>>> def add(a: int, b: int) -> int:
... return a + b
>>>
>>> s12.reduce(s17, add)
Some(29)
>>> s12.reduce(NONE, add)
Some(12)
>>> NONE.reduce(s17, add)
Some(17)
>>> NONE.reduce(NONE, add)
NONE
transpose()
Transposes an Option of a Result into a Result of an Option.
The mapping is as follows:
Some(Ok[T])is mapped toOk(Some[T])Some(Err[E])is mapped toErr[E]NONEis mapped toOk(NONE)
Returns:
| Type | Description |
|---|---|
Result[Option[T], E]
|
Result[Option[T], E]: The transposed result. |
Example:
>>> from pyochain import Some, Ok, Err, NONE
>>> Some(Ok(5)).transpose()
Ok(Some(5))
>>> NONE.transpose()
Ok(NONE)
>>> Some(Err("error")).transpose()
Err('error')
unwrap()
Returns the contained Some value.
Returns:
| Name | Type | Description |
|---|---|---|
T |
T
|
The contained |
Raises:
| Type | Description |
|---|---|
OptionUnwrapError
|
If the option is |
Example:
>>> from pyochain import Some
>>> Some("car").unwrap()
'car'
>>> from pyochain import NONE
>>> 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 |
required |
Returns:
| Name | Type | Description |
|---|---|---|
T |
T
|
The contained |
Example:
>>> from pyochain import Some, NONE
>>> Some("car").unwrap_or("bike")
'car'
>>> 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 |
required |
Returns:
| Name | Type | Description |
|---|---|---|
T |
T
|
The contained |
Example:
>>> from pyochain import Some, NONE
>>> k = 10
>>> Some(4).unwrap_or_else(lambda: 2 * k)
4
>>> NONE.unwrap_or_else(lambda: 2 * k)
20
unwrap_or_none()
Returns the contained Some value or None.
This is a convenience method for interoperability with APIs that use None to represent the absence of a value,
e.g. when interacting with standard Python libraries, or external dependencies.
This is NOT the recommended use for handling Option in any code that can be controlled, as it defeats the purpose of using Option for explicit handling of optional values.
Returns:
| Type | Description |
|---|---|
T | None
|
T | None: The contained |
Example:
>>> from pyochain import Option, Some, NONE
>>> NONE.unwrap_or_none() is None
True
>>> Some(42).unwrap_or_none()
42
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:
>>> from pyochain import Some, NONE
>>> Some((1, "a")).unzip()
(Some(1), Some('a'))
>>> 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]: |
Example:
>>> from pyochain import Some, NONE
>>> Some(2).xor(NONE)
Some(2)
>>> NONE.xor(Some(2))
Some(2)
>>> Some(2).xor(Some(2))
NONE
>>> NONE.xor(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:
>>> from pyochain import Some, NONE
>>> Some(1).zip(Some("a"))
Some((1, 'a'))
>>> Some(1).zip(NONE)
NONE
>>> NONE.zip(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
>>> from pyochain import Some, NONE
>>>
>>> @dataclass
... class Point:
... x: float
... y: float
>>>
>>> x = Some(17.5)
>>> y = Some(42.7)
>>> x.zip_with(y, Point)
Some(Point(x=17.5, y=42.7))
>>> x.zip_with(NONE, Point)
NONE
>>> NONE.zip_with(y, Point)
NONE