Skip to content

Instantly share code, notes, and snippets.

@rldotai
Created February 7, 2021 06:24
Show Gist options
  • Save rldotai/7578f12bb441b24c8a3a4ce5d7fa8c45 to your computer and use it in GitHub Desktop.
Save rldotai/7578f12bb441b24c8a3a4ce5d7fa8c45 to your computer and use it in GitHub Desktop.
A `getter` that brings JavaScript-style danger to Python.
import operator
from functools import reduce
def get(obj, key):
"""Get the item within `obj` corresponding to `key`.
If `obj` is subscriptable, return `obj[key]`, otherwise assume `key`
refers to an attribute and return `obj.key` instead.
"""
if hasattr(obj, '__getitem__'):
return obj[key]
else:
return getattr(obj, key)
def getter(*keys):
"""Returns a callable object that behaves like `operator.itemgetter`, except
that it falls back to getting attributes if the object is not subscriptable."""
if len(keys) == 1:
key = keys[0]
def g(obj):
if hasattr(obj, '__getitem__'):
return obj[key]
else:
return getattr(obj, key)
elif keys:
def g(obj):
ret = []
for key in keys:
if hasattr(obj, '__getitem__'):
ret.append(obj[key])
else:
ret.append(getattr(obj, key))
return tuple(ret)
return g
def get_in(keys: Sequence, obj, default=None, no_default=False):
"""Get the object specified by `keys`."""
try:
return reduce(get, keys, obj)
except (KeyError, IndexError, TypeError) as e:
if no_default:
raise e
else:
return default
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment