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

David Abrahams dave at boost-consulting.com
Wed May 28 23:30:59 CEST 2003


Stefan Seefeld <seefeld at sympatico.ca> writes:

> David Abrahams wrote:
>
>> If boost::python::type is a class like boost::python::dict is, then
>> type(x) is an instance of that class (OK so far) but type(type(x))
>> invokes type's copy constructor.  Those are just the syntax rules of
>> C++.  In order to be consistent with Python, type(type(x)) != type(x)
>> for most x,
>>     >>> type([])
>>     <type 'list'>
>>     >>> type(type([]))
>>     <type 'type'>
>> but that implies type's copy constructor doesn't make equivalent
>> copies (very bad in C++).
>
> That's where I'm lost. I don't see the copy constructor involved
> here.


the copy constructor signature is

  type( type const& )

the result of:

  type( x )

is to construct a temporary 'type' object, passing argument x.

therefore, the type of 

 type( x )

is 'type'

and if we pass that expression as a constructor argument to
type:

 type( type( x ) )
       ^^^^^^^^^-------has type 'type'

then we are constructing a temporary 'type' object, passing an
argument of type 'type'.  Ergo the copy constructor of 'type' is
called.  If we make it act like it does in Python, it will be a very
strange and dangerous c-ctor indeed.

> Assuming boost::python::type IS-A boost::pyton::object

Do you mean "is-an-instance-of?"  The scenario that causes a problem
is when boost::python::type is a class, just like boost::python::dict,
boost::python::tuple, et al.

> and there is a way to generate a boost::python::type for each
> boost::python::object ("it's type")

I guess you don't mean is-an-instance-of, because if you generate
several boost::python::type, objects, it must be a class.

> which means you would be able to hold a boost::python::type
> describing another boost::python::type's type (i.e.  the result of
> 'type(type([]))'.
>
> 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.

> Or in diagram form:
>
>   py_object       ->       py_type
>      ^                       ^
>      |                       |
> python::object        python::type


What are those things on the first line of the diagram?

> holding a python::object, you can construct a python::type object
> by accessing the 'py_type' object with 'PyObject_Type(object.ptr())'
> and wrapping this into a newly created python::type object.
>
> That would work no matter whether the original python::object was
> actually a type or an instance.

No duh.

> Then you could define comparison operators like:
>
> bool operator == (const python::type &t1, const python::type &t2)
> {
>    return t1.ptr() == t2.ptr(); // assuming only one python object exists
>                                 // per type
> }
>
> and
>
> bool operator <= (const python::type &t1, const python::type &t2)
> {
>    return PyObject_Subclass(t1, t2);
> }

Why bother?  If type were derived from object the operators would
already be available.

>>>the Python C Api provides 'type objects', so ultimately I would
>>>arrive at a single root of that 'instance' <-> 'type' tree
>> That makes no sense to me.  What is travelling up the tree to arrive
>> anywhere?
>
> sorry for not being clear. I was drawing a tree in my mind where
> parent nodes are types and child nodes are instances of those types.
> It would be a tree (well, actually onle two levels deep) since the
> root node would be a 'meta type', its children would be 'types', and
> their children would be 'instances'. All I meant to say was that you
> either walk up that tree when calling 'type(object)', or you stay
> where you are (i.e. the 'type' operator is idempotent when applied to
> a 'meta type').

No, it's not:

    class xyzmeta(type):
      def __init__(self, name, bases, dict):
           dict['x'] = 1
           dict['y'] = 1
           dict['z'] = 1
           return type.__call__(self,name,bases,dict)

    class XYZ(object):
        __metaclass__ = xyzmeta


    class xyzzy(XYZ): pass

    x = xyzzy()
    print 'class:',type(x)
    print 'metaclass:',type(type(x))
    print 'metametaclass:',type(type(type(x)))

>
> What am I missing ?

Seems like just about everything <wink>
But don't feel bad; nobody understands me.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list