I'm using Python 2.x and I'm wondering if there's a way to tell if a variable is a new-style class? I know that if it's an old-style class that I can do the following to find out.
import types
class oldclass:
pass
def test():
o = oldclass()
if type(o) is types.InstanceType:
print 'Is old-style'
else:
print 'Is NOT old-style'
But I haven't been able to find anything that works for new-style classes. I found this question, but the proposed solutions don't seem to work as expected, because simple values as are identified as classes.
import inspect
def newclass(object):
pass
def test():
n = newclass()
if inspect.isclass(n):
print 'Is class'
else:
print 'Is NOT class'
if inspect.isclass(type(n)):
print 'Is class'
else:
print 'Is NOT class'
if inspect.isclass(type(1)):
print 'Is class'
else:
print 'Is NOT class'
if isinstance(n, object):
print 'Is class'
else:
print 'Is NOT class'
if isinstance(1, object):
print 'Is class'
else:
print 'Is NOT class'
So is there anyway to do something like this? Or is everything in Python just a class and there's no way to get around that?
I believe this suffices:
Typically, you only need the
is_new_style_class
function for your purposes. Everything not a class will throw aTypeError
, so you might want to update it to:Examples:
int
, being a type, is by definition a new-style class (see Unifying types and classes in Python 2.2 ), or —if you prefer— new-style classes are by definition types.Checking for old-style classes is really easy. Just check
type(cls) is types.ClassType
. Checking for new-style classes is also easy,isinstance(cls, type)
. Note that the built-in types are also new-style classes.There seems to be no trivial way to distinguish built-ins from classes written in Python. New-style classes with __slots__ also don't have __dict__, just like
int
orstr
. Checking if str(cls) matches the expected pattern fails if the classes metaclass overrides the __str__ method. Some other ways that also don't work:cls.__module__ == '__builtin__'
(you can reassign __module__ on classes)not any(value is cls for value in vars(__builtins__).values())
(you can add stuff to the __builtin__ module).The fact that unification of builtin and userdefined types is so good that distinguishing them is non-trivial problem should imply to you the underlying point. You really shouldn't have to distinguish between them. It doesn't matter what the object is if it implements the expected protocol.
I think what you are asking is: "Can I test if a class was defined in Python code as a new-style class?". Technically simple types such as
int
are new-style classes, but it is still possible to distinguish classes written in Python from the built-in types.Here's something that works, although it's a bit of a hack:
Output from Python 2.6:
Here's a different way to do it:
It's not that "everything is a class": what you're bumping into is that "everything is an object" (that is, every (new-style) thing descends from "object").
But new-style classes are a "type" themselves (actually, the were introduced to bring classes and types together). So you can try checking for
Does that solve your problem?