[Python-ideas] A way out of Meta-hell (was: A (meta)class algebra)
Martin Teichmann
lkb.teichmann at gmail.com
Sat Feb 14 12:18:03 CET 2015
Hi Petr, Hi all,
> Just putting it in the standard library doesn't make sense, since it
> would still only be available there from Python 3.5 on (or whenever it
> gets in).
> It really makes more sense to put this into the *real* standard
> metaclass (i.e. `type`).
> The Python implementation can be on PyPI for projects needing the
> backwards compatibility.
That was what I was thinking about. Put the python implementation
on PyPI, so everyone can use it, and finally put the thing in the
standard library.
I actually prefer the standard library over adding it to type, it's
much less a hazzle. Given that there are use cases for metaclasses
not covered by PEP 422, I guess they won't ever be dropped,
so having two complicated things in C are not such a great idea in
my opinion if we can easily write one of them in Python.
> Not really, but you can rewrite the metaclass as a C extension (maybe
> after the Python variant is ironed out).
Well said, and yes, it needs ironing out. I just realized it doesn't work
since I'm calling __init_class__ before its __class__ is set. But this
is a solvable problem: Let's rewrite PEP 422 so that the initialization
is done on subclasses, not the class itself. This is actually a very
important usecase anyways, and if you need your method to be
called on yourself, just call it after the class definition! One line of
code should not be such a big deal.
I also simplified the code, requiring now that decorates __init_subclass__
with @classmethod.
Greetings
Martin
class Meta(type):
@classmethod
def __prepare__(cls, name, bases, namespace=None, **kwargs):
if namespace is not None:
cls.__namespace__ = namespace
if hasattr(cls, '__namespace__'):
return cls.__namespace__()
else:
return super().__prepare__(name, bases, **kwargs)
def __new__(cls, name, bases, dict, **kwargs):
return super(Meta, cls).__new__(cls, name, bases, dict)
def __init__(self, name, bases, dict, namespace=None, **kwargs):
super(self, self).__init_subclass__(**kwargs)
class Base(object):
@classmethod
def __init_subclass__(cls, **kwargs):
pass
SubclassInit = Meta("SubclassInit", (Base,), {})
More information about the Python-ideas
mailing list