[Python-ideas] Let's be more orderly!

Andrew Barnert abarnert at yahoo.com
Wed May 15 20:01:55 CEST 2013


From: Don Spaulding <donspauldingii at gmail.com>
Sent: Tuesday, May 14, 2013 6:57 PM


>On Tue, May 14, 2013 at 5:23 PM, Andrew Barnert <abarnert at yahoo.com> wrote:
>
>On May 14, 2013, at 12:53, Jonathan Eunice <jonathan.eunice at gmail.com> wrote:
>>
>>Using a compatible, separate implementation for OrderedDict is a fine way to gracefully extend the language, but it leaves ordering only half-accomodated. Consider:
>>>OrderedDict(a=2, b=3, c=7) 
>>If your proposal is to replace dict with OrderedDict, I think you need at least one use case besides OrderedDict's constructor.
>
>I don't understand the dismissal of OrderedDict.__init__ as an invalid use case.  It would be a substantial usability improvement to special-case OrderedDict at compile-time purely to get the ability to instantiate odict literals (not that I'm suggesting that).

I'm not dismissing it. If it were one of multiple varied use cases, it would contribute to the argument. But if the _only_ use case is something this special (we can't pass an OrderedDict to it, because that's obviously circular), it's not a good argument for a change with wide-ranging effects.

>In the interest of moving the discussion forward, I've had a few use cases along these lines.  Let's say I want to create simple HTML elements by hand:

>
>    def create_element(tag, text='', **attributes):
>        attrs = ['{}="{}"'.format(k,v) for k, v in attributes.items()]
>        return "<{0} {1}>{2}</{0}>".format(tag, ' '.join(attrs), text)
>    
>    print(create_element('img', alt="Some cool stuff.", src="coolstuff.jpg"))
>    <img src="coolstuff.jpg" alt="Some cool stuff."></img>

Well, HTML explicitly assigns no meaning to the order of attributes. And I think this is a symptom of a larger problem. Every month, half a dozen people come to StackOverflow asking how to get an ordered dictionary. Most of them are asking because they want to preserve the order of JSON objects—which, again, is explicitly defined as unordered. If code relies on the order of HTML attributes, or JSON object members, it's wrong, and it's going to break, and it's better to find that out early.

All that being said, sometimes HTML and JSON are read by humans as well as by software, at least for debugging purposes, and sometimes it's more readable with a specific (or at least consistent and predictable) order. So, the suggestion is definitely not without merit.

For some tests, you'll want the order scrambled to make sure you're not incorrectly relying on order, but, on the other hand, for debugging the output, you'll want it ordered to make it more readable.

>It's not that it's impossible to do, it's that dict-based API's would benefit from the function being able to decide on its own whether or not it cared about the order of arguments.  Having to express a kwargs-based or plain-old-dict-based function as a list-of-2-tuples function is... uncool.  ;-)


This is an interesting idea. If there were a way for the function to decide what type is used for creating its kwargs, you could do all kinds of cool things—have that switch you could turn on or off I just mentioned for different kinds of testing, or preserve order in "debug mode" but leave it arbitrary and as fast as possible in "production mode", or take a blist.sorteddict if you're intending to stash it and use it as the starting point for a blist.sorteddict anyway, or whatever. And it wouldn't affect the 99% of functions that don't care.

The syntax seems pretty obvious:

    def kwargs(mapping_constructor):
        def deco(fn):
            fn.kwargs_mapping_constructor = mapping_constructor
            return fn
        return deco

    @kwargs(OrderedDict)
    def foo(a, b, *args, **kwargs):
        pass

Handling this at the calling site is a bit harder, but still not that hard.

And this even solves the special problem of OrderedDict seemingly needing an OrderedDict: Just give it a mapping_constructor that creates a list of tuples.


More information about the Python-ideas mailing list