a few notes: >From the OP:
It would be cool to have a syntax that would unpack the dictionary to > values based on the names of the variables. Something perhaps like: > > a, b, c = **mydict > > which would assign the values of the keys 'a', 'b', 'c' to the variables. > a number of alternatives have been brought up, but I think it's important to note that this doesn't require naming the variables twice -- I think that's key to the proposal. Personally, I don't think that use case is common enough that it's something we should support with syntax. And while the OP drew a parallel with sequence unpacking, THAT doesn't make any assumptions about variable names on either side of the equals... The solutions that work with locals() being the only ones that do satisfy this, maybe a utility function that lets you specify which names you want unpacked would be handy. (a bit tricky to get the right locals() dict, though. Also: Paul Moore wrote: > The most common use case I find for this is when dealing with JSON (as > someone else pointed out). But that's a definite case of dealing with > data in a format that's "unnatural" for Python (by definition, JSON is > "natural" for JavaScript). > I suppose so - what is a dict in python (data structure) is an object in Javascript (code). I often find teasing out what is data and what is code to be a tricky code structure issue. However, most of the time when you pass JSON around it really is "data", rather than code, so the Python interpretation is the more appropriate one. > While having better support for working > with JSON would be nice, I typically find myself wishing for better > JSON handling libraries (ones that deal better with mappings with > known keys) than for language features. > exactly -- after all, under the hood, python objects have a _dict__ -- s mapping a JSON "object" to a Python object is really easy code to write: class JSObject: def __init__(self, js): self.__dict__.update(json.loads(js)) Of course, this doesn't deal with nested objects, but you can do that pretty easily, too: class JSObject: def __init__(self, js): """ initialized an object that matches the JSON passed in js is a JSON compatible python object tree (as produced by json.load*) """ for key, val in js.items(): if type(val) is dict: self.__dict__[key] = JSObject(val) else: self.__dict__[key] = val which won't deal with objects nested inside arrays. So, as I am hainvg fun: class JSObject: def __new__(cls, js_obj): """ create an object that matches the JSON passed in js is a JSON compatible python object tree (as produced by json.load*) """ if type(js_obj) is dict: self = super().__new__(cls) for key, val in js_obj.items(): self.__dict__[key] = JSObject(val) return self elif type(js_obj) is list: return [JSObject(item) for item in js_obj] else: return js_obj def __repr__(self): # note -- this does not do indentation... s = ['{\n'] for key, val in self.__dict__.items(): s.append('"%s": %s\n' % (key, str(val))) s.append('}') return "".join(s) I"m sure there are all sorts of edge cases this doesn't handle, but it shows it's pretty easy. However, I haven't seen a lib like this (though it may exist). I think the reason is that if you really want to convert JSON to Python objects, you probably want to use a schema and do validation, etc. And there are packages that do that. Also -- the Python data model is richer than the javascript one (dict keys that aren't identifiers, tuples vs lists, float vs int, ...) so another reason you probably don't want to unpack JSON into python Objects rather than dicts. This has gotten pretty off topic, though I think it shows that having a sample way to unpack a dict is probably not really helpful to the language - when you need to do that, you really need to have a bunch of extra logic in there anyway. > But of course, I could write > such a library myself, if it mattered sufficiently to me - and it > never seems *that* important :-) > So here it is :-) Not that I seems important to me -- just fun. -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception chris.bar...@noaa.gov
#!/usr/bin/env python import json class JSObject: def __new__(cls, js_obj): """ create an object that matches the JSON passed in js is a JSON compatible python object tree (as produced by json.load*) """ if type(js_obj) is dict: self = super().__new__(cls) for key, val in js_obj.items(): self.__dict__[key] = JSObject(val) return self elif type(js_obj) is list: return [JSObject(item) for item in js_obj] else: return js_obj def __repr__(self): # note -- this does not do indentation... s = ['{\n'] for key, val in self.__dict__.items(): s.append('"%s": %s\n' % (key, str(val))) s.append('}') return "".join(s) if __name__ == "__main__": some_json = """ { "this": "fred", "that": "bob", "a_list": [1,2,3], "a_number": 3.1459 } """ obj = JSObject(json.loads(some_json)) print(obj) assert obj.this == "fred" assert obj.that == "bob" assert obj.a_list == [1, 2, 3] assert obj.a_number == 3.1459 nested_json = """ { "this": "fred", "that": {"a_list": [1,2,3], "a_number": 3.1459, "double_nested": {"a": 45, "b": [1, 2, 3] } } } """ obj = JSObject(json.loads(nested_json)) print(obj) assert type(obj) == JSObject assert obj.this == "fred" assert type(obj.that) is JSObject assert obj.that.a_list == [1, 2, 3] assert obj.that.a_number == 3.1459 assert obj.that.double_nested.a == 45 assert obj.that.double_nested.b == [1, 2, 3] obj_in_list_json = """ { "this": [{"that": 45, "an_obj": {"fred": 34, "bob": [3,4,5] } }, 4, "a_string"] } """ obj = JSObject(json.loads(obj_in_list_json)) print(obj) assert type(obj) == JSObject assert type(obj.this) == list assert obj.this[1] == 4 assert obj.this[2] == "a_string" assert obj.this[0].that == 45 assert obj.this[0].an_obj.fred == 34 assert obj.this[0].an_obj.bob == [3, 4, 5]
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/