diff --git a/fastcore/basics.py b/fastcore/basics.py index 4e8dc2b4..3c94682e 100644 --- a/fastcore/basics.py +++ b/fastcore/basics.py @@ -716,9 +716,11 @@ def nested_attr(o, attr, default=None): try: for a in attr.split("."): if hasattr(o, a): o = getattr(o, a) + elif isinstance(o, (list, tuple, dict)) and a.isdigit():o = o[int(a)] elif hasattr(o, '__getitem__'): o = o[a] else: return default - except (AttributeError, KeyError): return default + except (AttributeError, KeyError, IndexError, TypeError): + return default return o # %% ../nbs/01_basics.ipynb diff --git a/nbs/01_basics.ipynb b/nbs/01_basics.ipynb index c9134171..a5347899 100644 --- a/nbs/01_basics.ipynb +++ b/nbs/01_basics.ipynb @@ -3903,6 +3903,13 @@ "test_fail(lambda: only([0,1]), contains='iterable has more than 1 item')" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -3915,12 +3922,28 @@ " try:\n", " for a in attr.split(\".\"):\n", " if hasattr(o, a): o = getattr(o, a)\n", + " elif isinstance(o, (list, tuple, dict)) and a.isdigit():o = o[int(a)]\n", " elif hasattr(o, '__getitem__'): o = o[a]\n", " else: return default\n", - " except (AttributeError, KeyError): return default\n", + " except (AttributeError, KeyError, IndexError, TypeError):\n", + " return default\n", " return o" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class TestObj:\n", + " def __init__(self): self.nested = {'key': [1, 2, {'inner': 'value'}]}\n", + "test_obj = TestObj()\n", + "\n", + "test_eq(nested_attr(test_obj, 'nested.key.2.inner'),'value')\n", + "test_eq(nested_attr([1, 2, 3], '1'),2)" + ] + }, { "cell_type": "code", "execution_count": null,