On 14Apr2020 23:08, Glenn Linderman <v+pyt...@g.nevcal.com> wrote:
On 4/14/2020 10:09 PM, Cameron Simpson wrote:
Like many others, I recently implemented one of these
__getattr__+__getitem__ SimpleNamespaces. I'm hacking on some
mappings which map dotted-names to values. So the natural
implementation is dicts or dict subclasses. But I'm also feeding
these to format strings, so I want to write:
"Hi {dotted.name}"
so I've made a nesting of SimpleNamespace so that I can use nice
dotted a.b.c.d type names in the format string. And because I'm
using .format_map, the top level namespace also supports
__getitem__.
Now, my dict subclass has a .ns() method returning one of the above
SimpleNamespace subclasses, but I can readily imagine a utility
function in collection that made such a thing. [...]
The below is something of a digression from the main topic, so before
digressing let me prefix with:
I'm with Raymond here. I think my position is that unlike most classes,
SimpleNamespace has very simple semantics, and no __getitem__ facility
at all, so making __getitem__ map to __getattr__ seems low impact.
Now the digression:
Interesting comments. So .ns allows you to convert a nested dict to a
dotted one "on demand" but the initial conversion only needs to do the
top level object?
In principle, yes. As it happens all of the subnamespaces are this class
as well, so one can __getitem__ on them too. I just... don't need to in
a format string.
As you might imagine this has sort of evolved from my initial problem of
accessing the dotted.name values in a format string, and it still has
some iteration to go there. str.format() requires completely filled out
keyword arguments, but str.format_map() accepts any mapping, so
__getitem__ can do whatever one wants. In my base class it is a thin
wrapper around getattr().
Because I'm starting with a flat dict like:
{ 'a': 1
'b': 2,
'b.c': 3,
'b.d': 4,
'b.d.e': 5,
}
the .ns() utility method constructs a complete nested tree of
SimpleNamespace objects.
That sounds similar to the glom that Nathaniel brought to the attention
of this thread, which I hadn't found before. But glom requires bulkier
syntax. When I read his example, I thought to myself "What if one could
write his 'glom(json_obj, "a.b.c")' example as json_obj['a.b.c']
Hah, I've got one of those, too, almost :-)
I've got a cs.sqlalchemy_utils module with a
get_json_field(column_value, field_name) function (it has a "set"
friend). It was intended to access a JSON blob database column, and the
field_name it accepts is a dotted name used to traverse a nesting of
dicts. I see its signature looks like glom().
or better as non_json_obj.a.b.c ? I can imagine an implementation of
my first "what-if" fully in the top-level object, but not of the second
(but my internals imagination is probably limited).
Nested dicts are a natural thing, and what you get from nested JSON
structures, particularly since JavaScript objects _are_ dicts, and the
attribute stuff is almost syntactic sugar.
Indeed, many of my use-cases are non-json, although a bunch are json
also.
My use case for the .ns() stuff is nonJSON.
One of the reasons my dict-subclass has a .ns() method to create a set
of nested namespaces is that an ordinary class has plenty of method
names which will overlap dict element names. So making the dict's
__getitem__ available via __getattr__ leads to trouble as soon as a key
matches a dict method name.
For this reason I gave it a separate .ns() method to construct the
SimpleNamespaces, which are a _transcription_ of the original values.
Cheers,
Cameron Simpson <c...@cskk.id.au>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/NDGACBBC5TLFSBYJYKIOB2IDZQELMC7O/
Code of Conduct: http://python.org/psf/codeofconduct/