[C++-sig] Re: accessing the python type system

David Abrahams dave at boost-consulting.com
Thu May 29 17:35:37 CEST 2003

Stefan Seefeld <seefeld at sympatico.ca> writes:

> Hi David,
> David Abrahams wrote:
>>>which means you would be able to hold a boost::python::type
>>>describing another boost::python::type's type (i.e.  the result of
>>>What do you want to copy here ?
>> I don't want to copy anything.  I have no choice; type(type(x)) calls
>> type's copy constructor.  I hope that's clear by now.
> 'type(x)' is a python expression, right ? 

The question was how to reflect that in the Boost.Python library, so
in the sentence above, no: type(x) is a C++ expression.

> The equivalent in C is
> PyObject *the_type = PyObject_Type(the_object);
> so your statement seems to imply that there already is some C++ wrapper
> code encapsulating a call to PyObject_Type, and resulting in some class'
> copy constructor to be called. Where can I find that ?

It doesn't exist.  I was responding speculatively to your request:

   "For example holding two python objects I'd like to test whether
   one's type is derived from the other's type, whether they are
   derived from a given type, i.e. things like 'type', 'isinstance',

In Python, 'type' is a type, so the most obvious way to reflect that
in C++ would be with a class called 'type', just as we have a class
called tuple in C++ whose constructor performs conversion to a tuple:

   x = tuple(some_list);

when I wrote the following, I was pointing out that it doesn't work:

    "In principle, there's no reason we shouldn't have something like
    you propose, only it should be a wrapper around Python's 'type'
    just the same way that boost::python::dict is a wrapper around
    Python's 'dict'...  but once you start go go down that road you
    get in trouble."

> I was assuming that the C++ API would provide a function somewhat
> similar to
> object type(const object &o)
> {
>    return object(borrowed(PyObject_Type(o.ptr())));
> }

I've been trying to say that I think the right answer is to provide a
boost::python::object called 'type', something like:

   object const type = extract<object>(PyTypeObject*);

so you could do:

   object y = type(x);

> or, with a suitable 'type' class defined,
> type get_type(const object &o)
> {
>    return type(borrowed(PyObject_Type(o.ptr())));
> }
> in which case there is no copy constructor anywhere.

The latter doesn't work, for all the reasons I've been listing.  Users
will expect to be able to do:

      object y = type(x);

which leads directly to the copy constructor problem.

Your statement that there's no copy ctor above is also not true; the
type object is copied when it is returned (though that copy may be
elided).  That is not just an irrelevant nitpick - if type(type(x)) is
not equivalent to type(x) you will get some very strange results.

>>>Or in diagram form:
>>>  py_object       ->       py_type
>>>     ^                       ^
>>>     |                       |
>>>python::object        python::type
>> What are those things on the first line of the diagram?
> the actual python objects (of type 'PyObject').

I see no reason not to use boost::python::object for both roles.

>>     print 'class:',type(x)
>>     print 'metaclass:',type(type(x))
>>     print 'metametaclass:',type(type(type(x)))
> fine, the last line tells me that the 'metametaclass' is a 'type'.
> Applying the 'type' operator to that still returns 'type'. It's just
> one level higher up than what I described. So what ?

So I can make it as many levels higher as I like; you said that type
applied to a metaclass is idempotent.  It just isn't true.

> All I was trying to get at is that a way to look at this is as a
> single rooted tree, where each parent node is the 'metaclass' of its
> respective child nodes.

OK, I think I understand how the Python type system is
organized...  again, I'm not sure what your point is.

Dave Abrahams
Boost Consulting

More information about the Cplusplus-sig mailing list