Optional
: Object wrapper for handling errors¶
-
class
carriage.
Optional
¶ An type for handling special value or exception.
Here is a contacts data constructed with multiple levels dictionary.
>>> contacts = { ... 'John Doe': { ... 'phone': '0911-222-333', ... 'address': {'city': 'hsinchu', ... 'street': '185 Somewhere St.'}}, ... 'Richard Roe': { ... 'phone': '0933-444-555', ... 'address': {'city': None, ... 'street': None}}, ... 'Mark Moe': { ... 'address': None}, ... 'Larry Loe': None ... }
If we need a function to get the formatted city name of some contact, we will have a lot of nested if statement for handling None or other unexpected values.
>>> def get_city(name): ... contact = contacts.get(name) ... if contact is not None: ... address = contact.get('address') ... if address is not None: ... city = address.get('city') ... if city is not None: ... return f'City: {city}' ... ... return 'No city available' >>> get_city('John Doe') 'City: hsinchu' >>> get_city('Richard Roe') 'No city available' >>> get_city('Mark Moe') 'No city available' >>> get_city('Larray Loe') 'No city available' >>> get_city('Not Existing') 'No city available'
Optional is useful on handling unexpected return values or exceptions and makes the code shorter and more readable.
>>> def getitem_opt(obj, key): ... """The same as Optional.from_getitem()""" ... try: ... return Some(obj[key]) ... except (KeyError, TypeError): ... return Nothing ... >>> def get_city2(name): ... return (getitem_opt(contacts, name) ... .and_then(lambda contact: getitem_opt(contact, 'address')) ... .and_then(lambda address: getitem_opt(address, 'city')) ... .filter(lambda city: city is not None) ... .map(lambda city: f'City: {city}') ... .get_or('No city available') ... ) ... >>> get_city2('John Doe') 'City: hsinchu' >>> get_city2('Richard Roe') 'No city available' >>> get_city2('Mark Moe') 'No city available' >>> get_city2('Larray Loe') 'No city available' >>> get_city('Not Existing') 'No city available'
Create Optional directly
>>> Some(3) Some(3) >>> Nothing Nothing
Create Optional by calling a function that may throw exception
>>> def divide(a, b): ... return a / b >>> Optional.from_call(divide, 2, 4, errors=ZeroDivisionError) Some(0.5) >>> Optional.from_call(divide, 2, 0, errors=ZeroDivisionError) Nothing
Create Optional from a value that may be None or other spectial value.
>>> adict = {'a': 1, 'b': 2, 'c': 3} >>> Optional.from_value(adict.get('c'), nothing_value=None) Some(3) >>> Optional.from_value(adict.get('d'), nothing_value=None) Nothing
-
and_then
(optional_func)¶ Return
optional_func(value)
if it is Someoptional_func
should return Optionaland_then
is useful for chaining functions that return Optional
-
filter
(pred)¶ Return Nothing if Some doesn’t satisfy the predicate
-
classmethod
from_call
(func, *args, errors=(<class 'Exception'>, ), **kwargs)¶ Create an Optional by calling a function
return Nothing if exception is raised
-
classmethod
from_getattr
(obj, attr_name)¶ Create an Optional by calling
obj.attr_name
return Nothing if AttributeError is raised
-
classmethod
from_getitem
(obj, key)¶ Create an Optional by calling
obj[key]
return
Nothing
ifKeyError
orTypeError
is raised
-
classmethod
from_value
(value, nothing_value=None)¶ Create an Optional from a value
return Nothing if
value
equals tonothing_value
-
get_or
(default)¶ Get the value if it is Some or get default if it is Nothing
-
get_or_none
()¶ Get the value if it is Some or get None if it is Nothing
-
is_nothing
()¶ Check if it is Nothing
-
is_some
()¶ Check if it is Some
-
map
(func)¶ Return
Some(func(value))
if it is Some
-
some
¶ Get the value if it is Some or raise AttributeError if it is not
-
-
carriage.
Nothing
¶