questions (& answers) about object, type, builtin types, class, metaclass and __getattribute__

Amirouche B. amirouche.boubekki at gmail.com
Tue Aug 23 16:47:07 EDT 2011


On Aug 22, 5:41 pm, Stephen Hansen <me+list/pyt... at ixokai.io> wrote:
> > 3) object's type is type : object.__class__ is type
> > 4) type parent object is object : type.__bases__ == (object,)
>
> Saying "type" and "parent" and the like for new-style classes is
> something of a misnomer. For "type" and "object", these things aren't
> constructed like this.
>
> What you have here is technically true if you go poke at it in the
> interpreter, but it doesn't really /mean/ anything because its not how
> these objects came to be and is circular and a bit confusing. These
> fundamental objects are created special.

The code snippet is here to illustrate how it is visible in the
interpreter. But
you are right.

> > 2) type is its own metaclass : type(type) is type ?
>
> Only in a purely theoretical way. It doesn't actually mean anything;
> moreover, type(something) is NOT how you determine somethings metaclass.
> Its how you determine somethings type.

see the answer to Steven D'Aprano. type(class_object) ==
a_meta_class_object


> The two concepts may be very distinct. Lots of things don't have
> metaclasses.

All object in new style class have a metaclass at least type.


> > 3) object's metaclass is type ?
>
> Again, only theoretically.

and again the famous "bootstrapping" make it like type created object.
>From the
outside world of the Python implementation object looks like a type
instance.


> > 5) type(any_object) == last_metaclass_..., which is, most of the time,
> > type ?
>
> Not necessarily at all. In fact, there is no way I'm aware of to
> determine if a metaclass was involved in a classes construction unless
> said metaclass wants to provide such a mechanism.
>
> Metaclasses are kind of a  hack. They are a way to hook into the class
> construction that's normally done and do something, anything you want,
> (even hijack the whole procedure and NOT construct a class at all, but
> play a song if you want) before its all finished.
>
> For example, this is a metaclass I've used:
>
>     PageTypes = {}
>
>     class _PageRegistration(type):
>         def __new__(cls, name, bases, dct):
>             klass = type.__new__(cls, name, bases, dct)
>             typename = name[:-9].lower()
>             if not typename:
>                 typename = None
>
>             PageTypes[typename] = klass
>             klass.Type = typename
>
>             return klass
>
>     class QueuePage(sc.SizedPanel):
>         __metaclass__ = _PageRegistration
>
> Note, the fact that my _PageRegistration metaclass inherits is itself a
> class which inherits from type is just one convenient way to write
> metaclasses. It could as simply have been just a function.
>
> Metaclasses are somewhat poorly named in that they are really, "creation
> hooks".


It the same issue in django, views are only function, until you need
complex
behavior and you want a "namespace" to put everything in it. IMO
that's why class
based views exists for complex cases. That said being able to declare
a metaclass
only as a functions is neat.


> > C) type vs class
> > ----------------
>
> > 1) Type is the metaclass of most classes
>
> Yes and no. Yes, in that most classes are created using the default
> mechanism inside CPython. The class body is executed in a scope, the
> resulting dictionary is bound to a new class object, bases and the like
> are set, and such.
>
> No in that it really just, IIUC, skips the whole "metaclass" part of the
> process because this 'default mechanism' doesn't need to call out into
> other code to do its job. At least, I think-- May be wrong here,
> metaclasses are something of a dark voodoo and I'm not 100% entirely
> familiar with the internal workings of CPython.
>
> But functionally, a metaclass is the chunk of code responsible for the
> actual physical construction of the class object.

For me it takes some variables, namely ``bases``, ``class_dict`` and
``configuration class_name`` and do something with it, probably
creating a
class_object which behaviour is parametred with the context. I did not
know
Python before new-style class, so probably for most people explainning
that
metaclasses are a creation hook is easier for them...

> > 4) It's in type.__call__ that happens calls to __new__ and __init__
>
> Again, "translates to" is suggesting "this is what happens when you do
> X", which I don't know if is strictly true. CPython inside may be
> optimizing this whole process.
> Especially when it comes to "magic
> methods", __x__ and the like -- CPython rarely uses __get*_ for those.
> It just calls the methods directly on the class object.

IIUC the code of Jython tells me what I've written. If the first part
of the algorithm
is "lookup for special methods" (what you seem to say) then we both
agree that we
agree, isn't it ?

Moreover I'm not looking in this part to understand how CPython works
internally,
but how Python works. Since I'm most proeffencient in Python I
translate it to
Python.

*Translates* means "it's a shortcut for".


> > 5) 3) => classes are instance of type
>
> > 6) Since type.__call__ is used to instantiate instance of instance of
> > type
> >    (rephrased: __call__ is used to instantiate classes) where is the
> > code which
> >    is executed when we write ``type(myobject)`` or ``type('MyClass',
> > bases, attributes)``
> >    __getattribute__ resolution algorithm (see E) tells me that it
> > should be type.__call__
> >    but type.__call__ is already used to class instatiation.
>
> Python callables can have more then one argument, and more then one
> behavior, and can choose to do more then one thing based on the number
> of arguments.
>
> They don't have overloading, but they can do it themselves.
>
> You've already proven that, and you already know that -- you're sorta
> over-complicating this :)
> You said:
>
>     MyClass = type('MyClass', (object,), {'attribute': 1, 'method': def
> method: pass })
>
> Type.__call__ does both.

Actually I missed that :/

> > D) builtin types
> > ----------------
>
> > 1) builtin types are their own metaclass ?
>
> Builtin types are constructed by the interpreter, and may or may not
> involve themselves with the class/type hierarchy. Even when they do,
> they may only do so partially.

That's the part I don't understand. How can they possibly work
differently. They
surrely make their bussiness in the infrastructure/algorithm already
in place in
type and object to but I cant spot the right piece of code that will
explain it.


> > 2) why function builtin type can not be subclassed ?
>
> Because functions are not classes. They're discrete things of their own.
> That a function object has a __class__ attribute is an example of a
> builtin partially involving itself in the class/type hierarchy, largely
> just for introspection purposes-- since functions are first-class
> citizens, you need to be able to pass it around and test to determine
> what one thing or another actually is.
>
> Now, functions ARE indeed PyObjects, the internal CPython representation
> of an object, of which all things are. But that's not really the same
> thing as ultimately inheriting from and involving itself in "object" and
> types/classes.

Coming with general idea about what are builtin type would make it
easier to
understand function objects.

What I can tell is that function objects behave like the instances of
a class, and
the class takes (at least) runnable code as arguments.

> > E) __getattribute__
> > -------------------
>
> > 1) ``my_object.attribute`` always translates to
> > ``my_object.__getattribute__('attribute')``
>
> No. __getattribute__ is a mechanism to hook into the attribute fetching
> mechanism. (As is __getattr__). It is NOT always invoked.
>
> Especially in the case of __*__ attributes, which by and large bypass
> such hooks, as the CPython internals is calling those functions directly
> on the class instances themselves.

see my answer in the other response



More information about the Python-list mailing list