On Apr 20, 2020, at 13:42, Christopher Barker <python...@gmail.com> wrote:
> 
> On Mon, Apr 20, 2020 at 12:17 PM Andrew Barnert <abarn...@yahoo.com> wrote:
>> 
>> A lot of JSON is designed to be consumed by JavaScript, where there is no 
>> real line (there is no dict type; objects have both dict-style and dot-style 
>> access). So in practice, a lot of JSON maps well to data, a lot maps well to 
>> objects, and some is mushily designed and doesn’t quite fit either way, 
>> because in JS they all look the same anyway.
> 
> Well, sure. Though JSON itself is declarative data. 

Sure, it’s a declarative format, it’s just that often it’s intended to be 
understood as representing an object graph.

> In Python, you need to decide how you want to work with it, either as an 
> object with attributes or a dict. But if you are getting it from JSON, it's a 
> dict to begin with. So you can keep it as a dict, or populate an object with 
> it. B ut populating that object can be automated:
> 
> an_instance = MyObject(**the_dict_from_JSON)

But unless your object graph is flat, this doesn’t work. A MyObject doesn’t 
just have strings and numbers, it also has a list of MySubObjects; if you just 
** the JSON dict, you get subobjs=[{… d1 … }, { … d2 … }], when what you 
actually wanted was subobjs=[MySubObject(**d) for d in …].

It’s not like it’s _hard_ to write code to serialize and deserialize object 
graphs as JSON (although it’s hard enough that people keep proposing a __json__ 
method to go one way and then realizing they don’t have a proposal to go the 
other way…), but it’s not as trivial as just ** the dict into keywords.

> > But, maybe even more importantly: even if you _do_ decide it makes more 
> > sense to stick to data for this API, you have the parallel `{'country': 
> > country, 'year': year}` issue, which is just as repetitive and verbose.
> 
> only if you have those as local variables -- why are they ?

Apologies for my overly-fragmentary toy example.

Let’s say you have a function that makes an API request to some video site to 
get the local-language names of all movies of the user-chosen genre in the 
current year.

If you’ve built an object model, it’ll look something like this:

    query = api.Query(genre=genre, year=datetime.date.today().year)
    response = api.query_movies(query)
    result = [movie.name[language] for movie in response.movies]

If you’re treating the JSON as data instead, it’ll look something like this:

    query = {'query': {'genre': genre, 'year': datetime.date.today().year}}
    response = requests.post(api.query_movies_url, json=query).json
    result = [movie['name'][language] for movie in response.movies]

Either way, the problem is in that first line, and it’s the same problem. (And 
the existence of ** unpacking and the dict() constructor from keywords means 
that solving either one very likely solves the other nearly for free.)

Here I’ve got one local, `genre`. (I also included one global representing a 
global setting, just to show that they _can_ be reasonable as well, although I 
think a lot less often than locals, so ignore that.) I think it’s pretty 
reasonable that the local variable has the same name as the selector 
key/keyword. If I ask “why do I have to repeat myself with genre=genre or 
'genre': genre”, what’s the answer?

If I have 38 locals for all 38 selectors in the API—or, worse, a 
dynamically-chosen subset of them—then “get rid of those locals” is almost 
surely the answer, but with just 1? Probably not. And maybe 3 or 4 is 
reasonable too—a function that select by genre, subgenre, and mood seems like a 
reasonable thing. (If it isn’t… well, then I was stupid to pick an application 
area I haven’t done much work in… but you definitely don’t want to just select 
subgenre without genre in many music APIs, because your user rarely wants to 
hear both hardcore punk and hardcore techno.) And it’s clearly not an accident 
that the local and the selector have the same name. So, I think that case is 
real, and not dismissible.

> I'm not saying it never comes up in well designed code -- it sure does, but 
> if there's a LOT of that, then maybe some refactoring is in order.

Yes. And now that you point that out, thinking of how many people go to 
StackOverflow and python-list and so on looking for help with exactly that 
antipattern when they shouldn’t be doing it in the first place, there is 
definitely a risk that making this syntax easier could be an antipattern 
magnet. So, it’s not just whether the cases with 4 locals are important enough 
to overcome the cost of making Python syntax more complicated; the benefit has 
to _also_ overcome the cost of being a potential antipattern magnet. For me, 
this proposal is right on the border of being worth it (and I’m not sure which 
side it falls on), so that could be enough to change the answer, so… good thing 
you brought it up.

But I don’t think it eliminates the rationale for the proposal, or even the 
rationale for using it with JSON-related stuff in particular.

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DOT5L2XHNZ4TWAWZAGVB2C6OCU5JF22L/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to