Skip to content

Instantly share code, notes, and snippets.

@andykais
Last active July 11, 2019 15:56
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 andykais/c1072e8e55b61228374c7e739fb01510 to your computer and use it in GitHub Desktop.
Save andykais/c1072e8e55b61228374c7e739fb01510 to your computer and use it in GitHub Desktop.
details two optional chaining methods
empty = None
deep = dict(a=dict(b='c'))
def chain_optional(func, default_value=None):
try:
return func()
except AttributeError:
return default_value
except TypeError:
return default_value
assert chain_optional(lambda: empty.test) is None
assert chain_optional(lambda: deep['a']['b']) is 'c'
EMPTY_IDENTIFIER = object()
class Optional(object):
def __init__(self, item=EMPTY_IDENTIFIER, default_value=None):
self.item = item
self.default_value = None
def __getattr__(self, name):
if isinstance(self.item, dict):
return Optional(self.item.get(name, EMPTY_IDENTIFIER))
elif hasattr(self.item, name):
return Optional(getattr(self.item, name))
else:
return Optional()
def __call__(self):
return self.default_value if self.item is EMPTY_IDENTIFIER else self.item
assert Optional(empty).test() is None
assert Optional(deep).a.b() is 'c'
assert Optional(deep).a.b.c.d() is None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment