From: Carl Banks on
[Following up to Terry Reedy's post since I don't see the original]

On May 24, 11:30 am, Terry Reedy <tjre...(a)udel.edu> wrote:
> On 5/24/2010 12:56 PM, Nathan Rice wrote:
>
> > I'm trying to do some fairly deep introspection and instrumentation of
> > instances and classes at runtime, and in order for everything to be
> > properly behaved I need to have radically different behavior in the
> > event that the thing passed to me is a wrapped class/instance.  Is there
> > a really good way, given an instance of a class, to determine if it is
> > wrapped or native?  Currently I check to see if it has __slots__ then
> > try to setattr a dummy variable but I imagine there is probably a
> > cleaner way.


There is no foolproof way, but the simplest and most reliable way is
to check the __flags__ attribute to see if it's a heap type, which all
Python new-style classes are and almost all C-defined types aren't:

cls.__flags__ & 512 # Py_TPFLAGS_HEAPTYPE


However, in Python 2.x, old-style classes aren't types and so don't
have a __flags__ attribute, so to cover that case you should check if
it's a classobj.

isinstance(cls,types.ClassType)


So a complete function would look something like this:

def is_probably_python_class(cls):
return isinstance(cls,types.ClassType) \
or (isinstance(cls,type) and cls.__flags__ & 512)


It's not foolproof for a couple reasons: it's possible to define heap
types in C, and it's possible to define a metatype that does things
differently, but I would suppose these cases are rare.

Incidentally, depending on your use case, you might find it helpful
also to know whether a type is a base type (meaning that it can be
subclassed). You can check that with cls.__flags__ & 1024. A
complete list of flags is in the include file object.h. Note that, in
order to be subclassable, a type defined in C has to behave like a
Python class to a certain extent. Thus you can assume a little bit
more about it.


Carl Banks