如何识别Python中的新式类变量?

14 投票
4 回答
2639 浏览
提问于 2025-04-15 21:41

我在用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'

但是我找不到适合新式类的方法。我看到过这个问题,不过里面提到的解决方案似乎不太管用,因为简单的值也被识别成类。

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 个回答

1

并不是说“所有东西都是类”,你遇到的问题是“所有东西都是一个对象”(也就是说,每一个(新式的)东西都是从“对象”这个概念派生出来的)。

不过,新式类本身也是一种“类型”(实际上,它们的出现是为了将类和类型结合在一起)。所以你可以试着检查一下

import types

type(o) == types.TypeType

这样能解决你的问题吗?

2

我觉得这样就足够了:

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 这个类型,按照定义来说就是一个新式类(具体可以参考 Python 2.2 中类型和类的统一),或者说,如果你愿意,新式类本质上就是类型。

8

我想你问的是:“我能否测试一个类是否在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 ')

撰写回答