[Python-ideas] OrderedDict for kwargs and class statement namespace

Nick Coghlan ncoghlan at gmail.com
Sat Mar 2 15:46:34 CET 2013


On Fri, Mar 1, 2013 at 7:37 AM, Eric Snow <ericsnowcurrently at gmail.com> wrote:
> On Thu, Feb 28, 2013 at 11:02 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> And PEP 422 is designed to make it easier to share a common __prepare__
>> method with different post processing.
>
> A major use case for __prepare__() is to have the class definition use
> an OrderedDict.  It's even a point of discussion in PEP 3115.  While I
> agree with the the conclusion of the PEP that using only OrderedDict
> is inferior to __prepare__(), I also think defaulting to OrderedDict
> is viable and useful.
>
> Using __prepare__() necessitates the use of a metaclass, which most
> people consider black magic.  Even when you can inherit from a class
> that has a custom metaclass (like collections.abc.ABC), it still
> necessitates inheritance and the chance for metaclass conflicts. While
> I'm on board with PEP 422, I'm not clear on how it helps here.

(catching up after moving house, haven't read the whole thread)

PEP 422 would make it useful to also add a "namespace" meta argument
to type.__prepare__ to give it a namespace instance to return. Then,
all uses of such a OrderedDict based metaclass can be replaced by:

    class MyClass(namespace=OrderedDict()):
        @classmethod
        def __init_class__(cls):
            # The class namespace is the one we passed in!

You could pass in a factory function instead, but I think that's a net
loss for readability (you would lose the trailing "()" from the empty
namespace case, but have to add "lambda:" or "functools.partial" to
the prepopulated namespace case)

Even if type wasn't modified, you could create your own metaclass that
accepted a namespace and returned it:

    class UseNamespace(type):
        def __prepare__(cls, namespace):
            return namespace

    class MyClass(metaclass=UseNamespace, namespace=OrderedDict())
        @classmethod
        def __init_class__(cls):
            # The class namespace is the one we passed in!

I prefer the approach of adding the "namespace" argument to PEP 422,
though, since it makes __init_class__ a far more powerful and
compelling idea, and between them the two ideas should cover every
metaclass use case that *only* customises creation rather than ongoing
behaviour.

I actually had this idea a week or so ago, but packaging discussions
and moving meant I had postponed writing it up and posting it.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia



More information about the Python-ideas mailing list