On 10/07/2013 04:27 AM, Steven D'Aprano wrote:

On Sun, 06 Oct 2013 20:17:33 +0200, Marco Buttu wrote:
>
>  >>> class FooMeta(type):
>...     def __call__(metacls, name, bases, namespace):
>...        print("FooMeta.__call__()")
...
>  From what I undestood, at the end of the class statement...
>
>  >>> def __call__(metacls, name, bases, namespace):
>...     print("FooMeta.__call__()")
>...
>  >>> FooMeta = type('FooMeta', (type,), {'__call__': __call__})

Your code snippet is correct. The "class FooMeta(type)..." statement is
syntactic sugar for type.__call__(...). But your description is
incorrect. This doesn't occur when you "call the metaclass type"...

Oh damn! Your are right :) Thanks to you and Peter. Now (I hope...) it should be clear for me:

>>> class FooMeta(type):
...     def __call__(meta, name, bases, namespace):
...         print('FooMeta.__call__()')
...
>>> class InstanceOfFooMeta(type, metaclass=FooMeta):
...     pass
...
>>> class Foo(metaclass=InstanceOfFooMeta):
...     pass
...
FooMeta.__call__()

I try to summarize the execution flow. The metaclass type creates FooMeta:

>>> class FooMeta(type):
...     def __call__(meta, name, bases, namespace):
...         print('FooMeta.__call__()')
...

This means at the end of the suite:

    FooMeta = type('FooMeta', (type,), {...})

So Python calls type. But type is an instance of type itself, so:

    FooMeta = type.__call__(type, 'FooMeta', (type,), {...})

At this point FooMeta is created. The next step is:

>>> class InstanceOfFooMeta(type, metaclass=FooMeta):
...     pass

This causes:

    InstanceOfFooMeta= FooMeta('InstanceOfFooMeta', (type,), {...})

Python is calling FooMeta, so it is calling an instance of type, so the code above becomes:

    InstanceOfFooMeta = type.__call__(FooMeta, 'InstanceOfMeta', \
        (type,), {...})


Finally:

>>> class Foo(metaclass=InstanceOfFooMeta):
...     pass
...
FooMeta.__call__()

In fact at the end of the suite of the class statement, Python calls an instance of FooMeta:

    Foo = InstanceOfFooMeta('Foo', (), {...})

so, definitively:

    Foo = FooMeta.__call__(InstanceOfFooMeta, 'Foo', (), {...})

Foo is None, but never mind. I just wanted to clarify me the class creation process.
Thanks again and congratulations for your PEP, it is written very very well

--
Marco Buttu
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to