Maybe-Else
Provides a `Maybe` class as a Python implementation of null-aware operators. It allows for safe chaining of operations, attribute access, item access, and method calls on potentially `None` values, falling back to a default if `None` is encountered at any point. This helps avoid explicit `if var is not None` checks, similar to Optional/Maybe types in other languages. The library is currently at version 0.2.1, with its first and only release in November 2019.
Warnings
- gotcha The `Maybe` class only catches `IndexError`, `KeyError`, `AttributeError`, and `TypeError` during chained operations. Any other exception type raised within the chain (e.g., `ValueError`, `ZeroDivisionError`) will propagate normally and must be handled outside the `Maybe` construct.
- gotcha If an intermediate operation in a `Maybe` chain *legitimately* returns `None` (i.e., `None` was not the initial wrapped value, nor did it result from a caught exception), `Maybe.else_()` will return `None` instead of the specified alternative value. This is because `None` is treated as a valid computed output.
- gotcha The truthiness of a `Maybe` object (`bool(Maybe(value))`) is determined by whether it would return its held `value` upon calling `else_()` (truthy) or the specified alternative (falsy). This might not always align with the truthiness of the underlying wrapped value.
- gotcha The library's `requires_python` isn't specified on PyPI, but its GitHub indicates support for Python 3.7+. Using it with older Python versions might lead to compatibility issues. Python itself does not strictly follow Semantic Versioning, and minor version updates (e.g., 3.7 to 3.8) can introduce subtle breaking changes for certain libraries.
Install
-
pip install maybe-else
Imports
- Maybe
from maybe_else import Maybe
Quickstart
from maybe_else import Maybe
# Basic usage: providing a default for None
result1 = Maybe(None).else_("default value")
print(f"Result 1: {result1}")
# Chained operations on a non-None value
data = {'user': {'name': 'Alice', 'age': 30}}
maybe_name = Maybe(data)['user'].get('name').upper().else_('Unknown')
print(f"Maybe name: {maybe_name}")
# Chained operations on a path with None
missing_data = {'user': None}
maybe_age = Maybe(missing_data)['user'].get('age').else_(0) # 'user' is None, so default is used
print(f"Maybe age (missing user): {maybe_age}")
# Chained operations with a legitimate None as an intermediate result
def get_nullable_value(x):
return None if x % 2 == 0 else x
result_none_output = Maybe(2).map(get_nullable_value).else_('Fallback')
print(f"Result None output (even number): {result_none_output}") # Expected: None, not 'Fallback' (see warnings)
result_non_none_output = Maybe(3).map(get_nullable_value).else_('Fallback')
print(f"Result Non-None output (odd number): {result_non_none_output}")