14

我正在使用 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

4 回答 4

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 ')
于 2010-04-16T17:01:09.027 回答
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 中统一类型和类),或者——如果您愿意的话——新型类是根据定义类型。

于 2010-04-16T19:33:14.487 回答
1

并不是说“一切都是类”:您遇到的是“一切都是对象”(也就是说,每个(新式)事物都源自“对象”)。

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

import types

type(o) == types.TypeType

这能解决你的问题吗?

于 2010-04-16T16:57:36.287 回答
-1

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

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

  • cls.__module__ == '__builtin__'(你可以在类上重新分配 __module__ )
  • not any(value is cls for value in vars(__builtins__).values())(你可以添加东西到 __builtin__ 模块)。

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

于 2010-04-16T20:38:14.947 回答