Attribute -> dict key descriptor. The target object must support ``__getitem__``, and optionally ``__setitem__``. Example: >>> from collections import defaultdict >>> class Me(dict): ... deep = defaultdict(dict) ... ... foo = _getitem_pr
| 92 | |
| 93 | |
| 94 | class getitem_property: |
| 95 | class="st">"""Attribute -> dict key descriptor. |
| 96 | |
| 97 | The target object must support ``__getitem__``, |
| 98 | and optionally ``__setitem__``. |
| 99 | |
| 100 | Example: |
| 101 | >>> from collections import defaultdict |
| 102 | |
| 103 | >>> class Me(dict): |
| 104 | ... deep = defaultdict(dict) |
| 105 | ... |
| 106 | ... foo = _getitem_property(&class="cm">#x27;foo') |
| 107 | ... deep_thing = _getitem_property(&class="cm">#x27;deep.thing') |
| 108 | |
| 109 | |
| 110 | >>> me = Me() |
| 111 | >>> me.foo |
| 112 | None |
| 113 | |
| 114 | >>> me.foo = 10 |
| 115 | >>> me.foo |
| 116 | 10 |
| 117 | >>> me[&class="cm">#x27;foo'] |
| 118 | 10 |
| 119 | |
| 120 | >>> me.deep_thing = 42 |
| 121 | >>> me.deep_thing |
| 122 | 42 |
| 123 | >>> me.deep |
| 124 | defaultdict(<type &class="cm">#x27;dictclass="st">'>, {'thing': 42}) |
| 125 | class="st">""" |
| 126 | |
| 127 | def __init__(self, keypath, doc=None): |
| 128 | path, _, self.key = keypath.rpartition(&class="cm">#x27;.') |
| 129 | self.path = path.split(&class="cm">#x27;.') if path else None |
| 130 | self.__doc__ = doc |
| 131 | |
| 132 | def _path(self, obj): |
| 133 | return (reduce(lambda d, k: d[k], [obj] + self.path) if self.path |
| 134 | else obj) |
| 135 | |
| 136 | def __get__(self, obj, type=None): |
| 137 | if obj is None: |
| 138 | return type |
| 139 | return self._path(obj).get(self.key) |
| 140 | |
| 141 | def __set__(self, obj, value): |
| 142 | self._path(obj)[self.key] = value |