如何识别类和对象?

2 投票
4 回答
856 浏览
提问于 2025-04-16 23:06

比如我有一个类

Class Cls:
   var 1 
   var 2

   def func(self):
      --- do some statement

现在,我可以简单地导入这个类并创建一个对象

import Cls
clsObj = Cls()

在这里,Cls是类,而clsObj是这个类的实例。有没有什么方法可以让我区分它们呢?

谢谢

相关问题:

4 个回答

1

我不太明白你为什么需要这样做,不过你可以这么操作:

if type(obj) == type:
    # It's a class.
else:
    # It's an instance of a class.
3

我觉得这个代码考虑了所有情况:

def isclass(obj):
    try:
        class_ = obj.__class__
    except AttributeError:
        # It's an old-style class
        return True
    try:
        class_.__class__
    except AttributeError:
        # It's an old-style instance
        return False
    # It's new-style
    return isinstance(obj, type)

现在我们来测试一下,确保它按预期工作:

def test():
    class OldStyle: pass

    class NewStyle(object): pass

    def class_factory():
        return type("DynamicClass", (object,), {})

    class MetaClass(type):
        def __new__(mcls, *args):
            if args:
                return type(*args)
            return class_factory()

    class WithMeta(object):
        __metaclass__ = MetaClass
        def __call__(self):
            return self

    confusing = WithMeta()

    for name, obj in locals().items():
        templ = "{0:>26s} == {1!r:>5}, {2:>26s} == {3!r:>5}"
        print templ.format(
            "isclass({0})".format(name), isclass(obj),
            "isclass({0}())".format(name), isclass(obj()))

输出:

         isclass(OldStyle) ==  True,        isclass(OldStyle()) == False
         isclass(NewStyle) ==  True,        isclass(NewStyle()) == False
         isclass(WithMeta) ==  True,        isclass(WithMeta()) == False
        isclass(MetaClass) ==  True,       isclass(MetaClass()) ==  True
    isclass(class_factory) == False,   isclass(class_factory()) ==  True
        isclass(confusing) == False,       isclass(confusing()) == False

MetaClassclass_factoryconfusing展示了在Python中什么算作一个类是有争议的,并且展示了isclass函数如何处理这些情况。

回复:agf

MetaClass并不是为了那样被实例化的,所以你避免错误的技巧其实只是让问题更复杂;对于MetaClass()打印“错误”会更正确。

你或者我写过MetaClass吗?我本来就是想让它那样被实例化的。我承认让一个元类(或者类工厂函数)每次调用都创建“相同”的类确实没什么意义,当然这也很让人困惑。不过,出于特定目的,我想说明的是,元类在被实例化时会创建一个类,而给MetaClass()传很多参数会在输出中造成混乱。:) 所以原则上我同意你的看法,但出于这个特定目的,我就是这样做的,而Python也允许我这么做。

__call__发生在__new__之前,所以WithMeta()confusingconfusing()展示的都是正确的。

如果你说“发生”是指“被解析、编译和绑定”,那么是的,这确实是先发生的。我不太明白你想表达什么。我同意这是正确的——当然是正确的,这段代码是写过并运行过的,我发布的结果也是我得到的,所以它一定是正确的。我不明白__call__和这个有什么关系。你能详细说明一下吗?

你实际上从未实例化WithMeta。你应该去掉那个__call__,并对confusing()显示错误。

我很确定我确实实例化了WithMeta

>>> WithMeta()
<isclass.WithMeta object at 0xb784574c>

当我写WithMeta()时,Python会检查type(WithMeta).__new__是否被定义,而它确实被定义了,所以Python会将类名、基类和命名空间字典作为参数传递给MetaClass.__new__()。它返回的是WithMeta类对象,这个对象是通过用相同的参数调用type得到的。

另一方面,confusing()等同于type(confusing).__dict__["__call__"](confusing),这只是返回参数,所以confusing == confusing()

3

没错,你可以直接用内置的 type() 函数,它可以告诉你一个对象是什么类型的。比如,输入 type(clsObj) 会返回“实例”这个结果。你也可以用 isinstance 来检查一下。
如果你输入 isinstance(clsObj, Cls),它会返回 True,说明 clsObjCls 的一个实例。而如果你输入 isinstance(Cls, Cls),它会返回 False,表示 Cls 不是它自己的实例。

撰写回答