Created
February 7, 2021 06:24
A `getter` that brings JavaScript-style danger to Python.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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