【问题标题】:Identifying that a variable is a new-style class in Python?确定变量是 Python 中的新型类?
【发布时间】:2011-02-08 22:09:40
【问题描述】:

我正在使用 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 中的所有内容都只是一个类,没有办法绕过它?

【问题讨论】:

  • 我正在研究一个递归序列化其子级的类,我希望能够判断该子级是否是一个类,并通过递归序列化其子级来处理它。
  • 您之前的评论似乎应该是实际问题,而原始问题看起来像是您为解决问题而采取的(可能是错误的)步骤。检查这个:catb.org/~esr/faqs/smart-questions.html#goal
  • 你可能想给我们一个class有另一个class作为孩子的例子;另外,请确保您不是在谈论 instancesinstance 拥有要序列化的子 instances 更为常见。
  • 我很抱歉,因为我的意思是一个实例而不是类本身。

标签: python class python-2.x


【解决方案1】:

我认为您要问的是:“我可以测试一个类是否在 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 ')

【讨论】:

  • 另外,根据 ~unutbu 的响应,可用于识别旧式类: def is_old_style(cls): return not hasattr(cls, 'init ')
  • 对不起,错误信息,但如果旧式类具有明确定义的 _init_ 方法,则上述 is_old_style(cls) 不起作用,但 type(cls)是类型。InstanceType 确实有效。
  • Daniel,is_new_style 的第一个版本需要改进:它不会被视为新样式:class NewStyle(object): __slots__= "attribute",
  • @ΤZΩΤZΙΟΥ,感谢您了解这一点。我已经更新了处理这种情况的代码。
  • 这两种方式看起来都很老套,但我也找不到更好的方法来做到这一点。在两者之间,我被第二个的简单性所吸引。
【解决方案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 作为一种类型,根据定义是新式类(请参阅Unifying types and classes in Python 2.2),或者——如果您愿意的话——新式类是按定义类型。

【讨论】:

  • 问题在于所有的东西(即使是老式的类和像 int 这样的基本类型)都会返回 true。
  • 您评论的问题是:旧式类返回 False,而int(根据定义是一种类型)一个新式类。跨度>
  • 问题在于 int 没有 _dict_ 属性,因此违反了新式类的“规则”之一。
  • @Dave:但这是您的规则还是误解?这是一个新型类:class NewStyle(object): __slots__= "attribute", 及其实例没有__dict__ 属性。
  • 实例测试不正确:成为object 并不意味着拥有新式类。示例:标准HTMLParser 模块的代码显示HTMLParser.HTMLParser 是一个老式类;但是,is_new_style_class_instance(HTMLParser()) 错误地返回 True。
【解决方案3】:

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

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

import types

type(o) == types.TypeType

这能解决你的问题吗?

【讨论】:

  • 对于 int 也返回 True
  • 不,旧样式和新样式类的表达式的计算结果为 false。但是,对于新样式的类而不是旧样式的类,这确实评估为 true: type(n.__class__) == types.TypeType 但是,对于像“int”这样的基本类型,它也评估为 true,所以它不完全正确我在找什么。
  • 没错,int 是新式类的一个实例。这就是统一的重点。
  • 但是 int 没有 _dict_ 属性,我假设所有类都有。
  • @Dave Johansen:你可以考虑纠正你的假设。
【解决方案4】:

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

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

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

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

【讨论】:

  • types.ClassTypePython 2-specific,使这个答案过时了。此外,一个reliable means,用于区分 CPython 下的内置类和用户定义的类。
猜你喜欢
  • 2017-03-25
  • 2010-09-28
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
相关资源
最近更新 更多