[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