在Python中确定变量是一个新式的类?

时间:2010-04-16 16:33:33

标签: python class python-2.x

我正在使用Python 2.x,我想知道是否有办法判断一个变量是否是一个新式的类?我知道如果这是一个旧式的课程,我可以做以下事情来找出答案。

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'

但是我找不到任何适用于新式课程的东西。我发现this question,但建议的解决方案似乎没有按预期工作,因为简单的值被识别为类。

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'

那么无论如何要做这样的事情?或者Python中的所有内容都只是一个类,并且没有办法解决这个问题?

4 个答案:

答案 0 :(得分:7)

我认为你要问的是:“我可以测试一个类是否在Python代码中被定义为一个新式的类?”。技术上简单的类型,例如int 新样式类,但仍然可以区分用Python编写的类和内置类型。

这是有效的,虽然它有点像黑客:

def is_new_style(cls):
    return hasattr(cls, '__class__') \
           and \
           ('__dict__' in dir(cls) or hasattr(cls, '__slots__'))


class new_style(object):
    pass

class old_style():
    pass

print is_new_style(int)
print is_new_style(new_style)
print is_new_style(old_style)

Python 2.6的输出:

False
True
False

这是一种不同的方式:

def is_new_style(cls):
    return str(cls).startswith('<class ')

答案 1 :(得分:1)

并不是说“一切都是一个阶级”:你所遇到的是“一切都是对象”(也就是说,每一个(新式)事物都来自“对象” )。

但是新式类本身就是一种“类型”(实际上,它们是为了将类和类型组合在一起而引入的)。所以你可以尝试检查

import types

type(o) == types.TypeType

这能解决您的问题吗?

答案 2 :(得分:1)

我相信这就足够了:

def is_new_style_class(klass):
    return issubclass(klass, object)

def is_new_style_class_instance(instance):
    return issubclass(instance.__class__, object)

通常,您只需要is_new_style_class功能。所有不是类的都会抛出TypeError,因此您可能希望将其更新为:

def is_new_style_class(klass):
    try:
        return issubclass(klass, object)
    except TypeError:
        return False

示例:

>>> class New(object): pass
... 
>>> is_new_style_class(New)
True
>>> class Old: pass
... 
>>> is_new_style_class(Old)
False
>>> is_new_style_class(1)
False
>>> is_new_style_class(int)
True

int,作为一个类型,根据定义是一个新风格的类(参见Unifying types and classes in Python 2.2),或者 - 如果您愿意 - 新风格类是按照定义类型。

答案 3 :(得分:-1)

检查旧式课程非常简单。只需查看type(cls) is types.ClassType即可。检查新式类也很容易,isinstance(cls, type)。请注意,内置类型也是新式类。

似乎没有简单的方法来区分内置函数和用Python编写的类。带有__slots__的新式类也没有__dict__,就像intstr一样。如果类metaclass重写__str__方法,则检查str(cls)是否与预期模式匹配失败。其他一些方法也不起作用:

  • cls.__module__ == '__builtin__'(您可以在课程上重新分配__module__)
  • not any(value is cls for value in vars(__builtins__).values())(您可以在__builtin__模块中添加内容)。

内置和用户定义类型的统一是如此之好以至于区分它们是非平凡的问题这一事实应该意味着你的基本观点。你真的不应该区分它们。如果它实现了预期的协议,那么对象是什么并不重要。