[Python-Dev] PyInstance_Check() and new-style classes

Phillip J. Eby pje at telecommunity.com
Mon Jul 12 18:12:49 CEST 2004


At 09:15 AM 7/12/04 -0500, Eric Wilhelm wrote:
># The following was supposedly scribed by
># Phillip J. Eby
># on Monday 12 July 2004 08:48 am:
>
> >If you want to find out whether a type was defined in Python or C, you can
> >use the "heap type" flag in the type structure.  Note, however, that this
> >will not let you distinguish between core C types and C extension types, so
> >using it might be a bad idea if the reason you're using Python is to use a
> >Python module written in C!
>
>I'm not sure if I understand what this flag is telling me.  According to the
>api/type-structs.html, Py_TPFLAGS_HEAPTYPE is set when the object is
>allocated.  To me, that reads that it would be set for builtin tuples, etc
>even if they were not subclassed.

A "heap type" is a type whose type struct is in heap memory.  A "non-heap" 
type is one whose type struct is declared statically, i.e. in C code.

So, a non-heap type is either a built-in type, or an extension type 
provided by a C extension module.  A heap type is either one coded in pure 
Python, or potentially a C extension coded in an unusual fashion (e.g. via 
Pyrex).


> >Why do you want to distinguish between different kinds of objects?  Is it
> >because Perl needs/wants Python strings and numbers to become
> >scalars?
>
>To have a useful binding, yes.
>
>We want to create constructors for constructors, methods for methods, and
>translate everything else into native scalars, hashes, and lists.

For mappings and sequences (other than Python dicts and lists) you might 
consider using Perl's "tie" facilities, to avoid undesirable changes in 
semantics.


> >Perhaps you should simply convert those types that you want an
> >exact conversion for, and consider everything else to be
> >"instances".
>
>That has been the current approach.  The trouble is, we need to know that 
>they
>are instances so we can bless them, and we need to know that they are
>instances of a user-defined class, even if they are subtypes of builtin
>types.


Here's what I would suggest:

1. Use 'PyWhatever_CheckExact()' tests for known builtin types, where you 
can convert them with full fidelity.  (Or use a switch on the object's 
ob_type field.)

2. For all other types, convert to a blessed reference, *unless* you either 
call an explicit conversion function or method, or use Perl's context 
facilities to decide how to interpret the object.  If the context wants an 
array, test for sequenceness or iterability.  If the context wants a hash, 
test for mapping-ness.  If the context wants a scalar, test for number or 
stringness.

I'm making the assumption here that your code has some way of knowing what 
kind of context the surrounding code provides.  If not, you'll have to have 
conversions like:

     perl_string($python_ref)
     perl_number($python_ref)
     perl_hash($python_ref)
     perl_array($python_ref)
     perl_function($python_ref)

etc.  (Of course, your function names will probably vary.)

Essentially, if you want to be able to map Python objects to Perl values 
with full fidelity, you really need to be able to say what kind of Perl 
value you want, and that was really true even *before* Python 2.2.  DWIM 
isn't really an option except for builtin types, and *only* for the builtin 
types, not their subclasses.





More information about the Python-Dev mailing list