Skip to content

Instantly share code, notes, and snippets.

@fre-sch
Created February 24, 2021 08:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fre-sch/16dfe16fda1a2a1d2ee7083634d65271 to your computer and use it in GitHub Desktop.
Save fre-sch/16dfe16fda1a2a1d2ee7083634d65271 to your computer and use it in GitHub Desktop.
Chainable None-Aware Wrapper
from dataclasses import dataclass
class Maybe:
def __init__(self, value):
self.value = value
def bind(self, f):
if self.value is None:
return self
result = f(self.value)
if isinstance(result, Maybe):
return result
return Maybe(result)
def __iter__(self):
if self.value is None:
return
yield self.value
def __bool__(self):
return self.value is not None
def __getattr__(self, item):
return self.bind(lambda v: getattr(v, item))
# def __setattr__(self, key, value):
# return self.bind(lambda v: setattr(v, key, value))
def __getitem__(self, item):
return self.bind(lambda v: v[item])
# def __setitem__(self, key, value):
# def setter(v): v[key] = value
# return self.bind(setter)
def __invert__(self):
return next(iter(self), None)
def __call__(self, *a, **kw):
return self.bind(lambda v: v(*a, **kw))
@dataclass
class Cart:
order: object
class Order:
def __init__(self, items, currency):
self.items = items
self.currency = currency
def total(self):
return sum(
~Maybe(order_item).price or 0
for order_item in self.items
)
@dataclass
class OrderItem:
price: int
cart = Cart(
Order(
[
OrderItem(100),
OrderItem(100),
None
],
"EUR"
)
)
assert ~Maybe(cart).order.total() == 200
print(~Maybe(cart).order.items[2].price)
cart.order = None
assert ~Maybe(cart).order.total() is None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment