如何检查对象是不是是新型用户定义类的实例?

Posted

技术标签:

【中文标题】如何检查对象是不是是新型用户定义类的实例?【英文标题】:How to check if object is instance of new-style user-defined class?如何检查对象是否是新型用户定义类的实例? 【发布时间】:2013-01-14 19:00:19 【问题描述】:

代码:

import types


class C(object):
    pass


c = C()
print(isinstance(c, types.InstanceType))

输出:

False

检查对象是否是新样式类的用户定义类的实例的正确方法是什么?

更新:

我想进一步强调检查对象类型是否为用户定义。根据文档:

types.InstanceType 用户定义的类的实例类型。

UPD2:

好吧 - 不“正确”的方式也可以。

UPD3:

还注意到模块types中没有set的类型

【问题讨论】:

这是一个奇怪的需求,它有什么用? 我正在尝试编写一个简单的函数来测量作为参数提供的对象占用了多少内存 嗯,我还是不明白。为什么需要知道它是否是用户定义的类?在 yes 情况下与 no 情况不同,你会怎么做? @NedBatchelder 可能是__slots__ 问题或类似问题。 【参考方案1】:

这告诉我们如果是真的。

if issubclass(checkthis, (object)) and 'a' not in vars(__builtins__):print"YES!"

第二个参数是要检查的类的元组。 这很容易理解,我相信它有效。 [编辑(对象)到(对象,)感谢邓肯!]

【讨论】:

您的第二个参数只是object。括号不会神奇地将它变成一个元组:逗号构成元组,所以(object,) 将是一个单元素元组。但是在这种情况下,只传递object 可以正常工作,因为issubclass() 的第二个参数可以是issubclass() 作为其第二个参数的类或元组。 (是的,定义是递归的,因此您可以使用嵌套的类元组。) issubclass(int, (object,)) 也返回 True ,因此不符合 OP 的要求。 实际上,OP 说“不是“正确”的答案”,我理解这意味着即使它不是官方方式也可以工作。但我可以看到混乱:取消投票。【参考方案2】:

您可以将x.__class__ 检查与'__dict__' in dir(x)hasattr(x, '__slots__') 的存在(或不存在)结合起来,作为区分新/旧样式类和用户/内置对象的一种简单方法。

实际上,同样的建议出现在https://***.com/a/2654806/1832154

def is_instance_userdefined_and_newclass(inst):
    cls = inst.__class__
    if hasattr(cls, '__class__'):
        return ('__dict__' in dir(cls) or hasattr(cls, '__slots__'))
    return False

>>> class A: pass
... 
>>> class B(object): pass
... 
>>> a = A()
>>> b = B()
>>> is_instance_userdefined_and_newclass(1)
False
>>> is_instance_userdefined_and_newclass(a)
False
>>> is_instance_userdefined_and_newclass(b)
True

【讨论】:

除非在 c 库中定义的对象会失败。我想hackish这个词是合适的。 @Antimony 您通常会在 C 库中创建(即编码)一个类并在运行 python 代码时加载它吗?通过用户定义,我只是认为用户纯粹使用 Python 创建它,而不依赖于 C 代码的 CPython API。而且我知道这种方法可能会失败,但是对于给定的问题没有其他方法可以解决(您的答案无效)。 @mmgp 好像这就是答案,谢谢!如果不会发布更少的骇人听闻的解决方案,我将再等 4 天并接受/奖励您的答案。 太棒了。我今天需要这个,原因与三年前 Gill 需要这个的原因完全相同:memory profiling。当递归分析 user-defined 对象消耗的空间以及这些对象传递引用的 user-defined 引用的完整树时,递归自然会在 built-在 对象中。这个简单的(尽管有点骇人听闻)测试救了我的加拿大培根。 与此相关,is_instance_userdefined_and_newclass() 的最后三行简化为一条语句:return hasattr(cls, '__class__') and ('__dict__' in dir(cls) or hasattr(cls, '__slots__'))。获胜的效率提升微不足道。【参考方案3】:

也许我可以使用消除方法 - 不明确检查对象是否是用户定义类的实例 - isinstance(object, RightTypeAliasForThisCase),但检查对象是否不是“基本”类型之一。

【讨论】:

【参考方案4】:

我不确定“正确”的方法,但一种简单的测试方法是旧样式类的实例具有类型“实例”而不是它们的实际类。

所以type(x) is x.__class__type(x) is not types.InstanceType 应该都可以工作。

>>> class Old:
...     pass
...
>>> class New(object):
...     pass
...
>>> x = Old()
>>> y = New()
>>> type(x) is x.__class__
False
>>> type(y) is y.__class__
True
>>> type(x) is types.InstanceType
True
>>> type(y) is types.InstanceType
False

【讨论】:

打败我。如果您不介意,我会在您的答案中添加链接 欢迎添加链接。 实际上type(x) is x.__class__ 会返回True,即使x = 1。所以这种方式和isinstance(x, types.InstanceType)不相似 我还不能编辑你的问题,但是here's the relevant question with more information about this @Gill 那是因为int 是一个新的样式类。根据您实际编辑的问题,您似乎不走运。

以上是关于如何检查对象是不是是新型用户定义类的实例?的主要内容,如果未能解决你的问题,请参考以下文章

检查对象是不是是类的实例(但不是其子类的实例)

检查对象是不是是类的“直接实例”

Python——检查对象是不是是某个模块中任何类的实例

Java类的定义与类的实例化

Python 检查类的实例

如何检查某个用户是否具有某个权限对象上定义的某种权限