Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to find out if an object is a class?

0 views
Skip to first unread message

szczepiq

unread,
Aug 7, 2008, 5:36:37 PM8/7/08
to
Pardon me for most likely a dummy question but how do I find out if an
object is a class?

I need something like that:

def foo(self, obj):
if (obj is a class):
some stuff

Wojtek Walczak

unread,
Aug 7, 2008, 5:53:23 PM8/7/08
to
Dnia Thu, 7 Aug 2008 14:36:37 -0700 (PDT), szczepiq napisa³(a):

> Pardon me for most likely a dummy question but how do I find out if an
> object is a class?


Use types.ClassType:

>>> class Q:
... pass
...
>>> import types
>>> isinstance(Q, types.ClassType)
>>> True

--
Regards,
Wojtek Walczak,
http://www.stud.umk.pl/~wojtekwa/

Ben Finney

unread,
Aug 7, 2008, 7:50:04 PM8/7/08
to
szczepiq <szcz...@gmail.com> writes:

> Pardon me for most likely a dummy question but how do I find out if
> an object is a class?

You can test using 'isinstance'. However, using that is a bad code
smell, which requires investigation as to the reason.

Presumably you want to know whether it's a class in order to use it
for instantiating it. It is usually more Pythonic to use the object as
intended, and allow the object itself to tell you (via exceptions)
when it's not behaving as you expect.

>>> def foo(spam_class):
... spam_arg = 10
... spam_instance = spam_class(spam_arg)
... # … do stuff with spam_instance …
...
>>> foo(int)
>>> foo("not a class")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
TypeError: 'str' object is not callable

> I need something like that:
>
> def foo(self, obj):
> if (obj is a class):
> some stuff

Why do you think you need to test whether an object is a class? What
problem are you trying to solve?

--
\ “I got fired from my job the other day. They said my |
`\ personality was weird. … That's okay, I have four more.” |
_o__) —Bug-Eyed Earl, _Red Meat_ |
Ben Finney

Terry Reedy

unread,
Aug 7, 2008, 8:56:56 PM8/7/08
to pytho...@python.org

Wojtek Walczak wrote:
> Dnia Thu, 7 Aug 2008 14:36:37 -0700 (PDT), szczepiq napisa�(a):
>> Pardon me for most likely a dummy question but how do I find out if an
>> object is a class?
>
>
> Use types.ClassType:
>
>>>> class Q:
> ... pass
> ...
>>>> import types
>>>> isinstance(Q, types.ClassType)
>>>> True

That is only true and only works for 2.x old-style classes and not for
2.x new-style classes and all 3.0 classes, for which isinstance(Q,type)
is True.

>>> class old: pass
...
>>> type(old)
<type 'classobj'>
>>> class new(object): pass
...
>>> type(new)
<type 'type'>

Carl Banks

unread,
Aug 7, 2008, 9:26:46 PM8/7/08
to
On Aug 7, 8:56 pm, Terry Reedy <tjre...@udel.edu> wrote:
> Wojtek Walczak wrote:
> > Dnia Thu, 7 Aug 2008 14:36:37 -0700 (PDT), szczepiq napisa (a):
> >> Pardon me for most likely a dummy question but how do I find out if an
> >> object is a class?
>
> > Use types.ClassType:
>
> >>>> class Q:
> > ...    pass
> > ...
> >>>> import types
> >>>> isinstance(Q, types.ClassType)
> >>>> True
>
> That is only true and only works for 2.x old-style classes and not for
> 2.x new-style classes and all 3.0 classes, for which isinstance(Q,type)
> is True.

isinstance(Q,type) is also true for built in types and C extension
types, which may or may not be what the OP wants.

The most accurate way I can think of to check for a class defined in
Python is to test the type's tp_flags field for Py_TPFLAGS_HEAPTYPE
bit, but I don't know of any simple way to check for it from Python.
It's still possible for it to fail since someone could create heap
types in C though I'd expect that's very rare.


Carl Banks

Terry Reedy

unread,
Aug 8, 2008, 12:04:48 AM8/8/08
to pytho...@python.org

Carl Banks wrote:
> On Aug 7, 8:56 pm, Terry Reedy <tjre...@udel.edu> wrote:

>> That is only true and only works for 2.x old-style classes and not for
>> 2.x new-style classes and all 3.0 classes, for which isinstance(Q,type)
>> is True.
>
> isinstance(Q,type) is also true for built in types and C extension
> types

That is rather the point of new and improved classes -- that the
implementation language of a class be pretty much irrelevant from the
user api viewpoint ;-)

Stefan Behnel

unread,
Aug 8, 2008, 2:31:59 AM8/8/08
to
Ben Finney wrote:

> szczepiq writes:
>
>> Pardon me for most likely a dummy question but how do I find out if
>> an object is a class?
>
> Presumably you want to know whether it's a class in order to use it
> for instantiating it. It is usually more Pythonic to use the object as
> intended, and allow the object itself to tell you (via exceptions)
> when it's not behaving as you expect.

This also allows passing a factory function instead of a class, BTW.

I recently had the reverse case that a (stupidly implemented) extension module
required a callback function and I wanted to pass a function wrapped in a
wrapper object. That failed, because it specifically checked for the argument
being a function, not just a callable object. I had to pull quite a number of
tricks to reimplement the wrapper class as a function (thank god, it's Python!).

Stefan

Miles

unread,
Aug 8, 2008, 4:51:24 AM8/8/08
to pytho...@python.org
On Fri, Aug 8, 2008 at 2:31 AM, Stefan Behnel wrote:
> I recently had the reverse case that a (stupidly implemented) extension module
> required a callback function and I wanted to pass a function wrapped in a
> wrapper object. That failed, because it specifically checked for the argument
> being a function, not just a callable object. I had to pull quite a number of
> tricks to reimplement the wrapper class as a function (thank god, it's Python!).

You really only needed one trick:

def functionize(callable):
return lambda *args, **kwargs: callable(*args, **kwargs)

:)

-Miles

Christian Heimes

unread,
Aug 8, 2008, 9:04:56 AM8/8/08
to pytho...@python.org
szczepiq wrote:
> Pardon me for most likely a dummy question but how do I find out if an
> object is a class?

For God's sake don't reinvent the wheel! The 'inspect' module (part of
the Python standard library) has a functions isclass(). It does the
proper tests for new style and old style classes.

import inspect
inspect.isclass(something)

Christian

Stefan Behnel

unread,
Aug 8, 2008, 10:38:14 AM8/8/08
to

Congratulations, you found the trivial case.

Stefan

Steven D'Aprano

unread,
Aug 8, 2008, 7:02:21 PM8/8/08
to

What other cases are there? It takes any callable, and returns a function
that calls the callable. What else do you need? This is not a rhetorical
question.

The above works as expected for classes and methods:

>>> x = functionize(float)
>>> type(x)
<type 'function'>
>>> x('123')
123.0
>>> L = [1,2,3]
>>> y = functionize(L.append)
>>> y(44)
>>> L
[1, 2, 3, 44]

It even works for recursive functions:

>>> def fact(n):
... if n <= 1: return 1
... else: return n*fact(n-1)
...
>>> z = functionize(fact)
>>> z(5)
120


I haven't tested it on classmethods, staticmethods, or instances with a
__call__ method, but I see no reason why it wouldn't work with them. What
am I missing?

--
Steven

Stefan Behnel

unread,
Aug 10, 2008, 1:14:05 AM8/10/08
to
Steven D'Aprano wrote:
> On Fri, 08 Aug 2008 16:38:14 +0200, Stefan Behnel wrote:
>> Miles wrote:
>>> On Fri, Aug 8, 2008 at 2:31 AM, Stefan Behnel wrote:
>>>> I recently had the reverse case that a (stupidly implemented)
>>>> extension module required a callback function and I wanted to pass a
>>>> function wrapped in a wrapper object. That failed, because it
>>>> specifically checked for the argument being a function, not just a
>>>> callable object. I had to pull quite a number of tricks to reimplement
>>>> the wrapper class as a function (thank god, it's Python!).
>>> You really only needed one trick:
>>>
>>> def functionize(callable):
>>> return lambda *args, **kwargs: callable(*args, **kwargs)
>> Congratulations, you found the trivial case.
>
> What other cases are there? It takes any callable, and returns a function
> that calls the callable. What else do you need? [...] What am I missing?

The words "stupidly implemented" above? :)

I have to set the callback in more than one place and (believe it or not) the
library behaves (slightly) different when you pass different callbacks. The
right way to use the above approach would be to wrap the callback right before
passing it into the library - which I can't do, as that would give me a
different function object each time. Also, most of the time I actually pass a
function, except in one case where I need a wrapper for an existing function.
So the solution I chose was to change the original wrapper class itself
instead of re-wrapping it, so that I get the expected object right away.

As usual, it's all about the details.

Stefan

0 new messages