如何识别类和对象?
比如我有一个类
Class Cls:
var 1
var 2
def func(self):
--- do some statement
现在,我可以简单地导入这个类并创建一个对象
import Cls
clsObj = Cls()
在这里,Cls是类,而clsObj是这个类的实例。有没有什么方法可以让我区分它们呢?
谢谢
相关问题:
4 个回答
我不太明白你为什么需要这样做,不过你可以这么操作:
if type(obj) == type:
# It's a class.
else:
# It's an instance of a class.
我觉得这个代码考虑了所有情况:
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
MetaClass、class_factory和confusing展示了在Python中什么算作一个类是有争议的,并且展示了isclass函数如何处理这些情况。
回复:agf
MetaClass并不是为了那样被实例化的,所以你避免错误的技巧其实只是让问题更复杂;对于MetaClass()打印“错误”会更正确。
你或者我写过MetaClass吗?我本来就是想让它那样被实例化的。我承认让一个元类(或者类工厂函数)每次调用都创建“相同”的类确实没什么意义,当然这也很让人困惑。不过,出于特定目的,我想说明的是,元类在被实例化时会创建一个类,而给MetaClass()传很多参数会在输出中造成混乱。:) 所以原则上我同意你的看法,但出于这个特定目的,我就是这样做的,而Python也允许我这么做。
__call__发生在__new__之前,所以WithMeta()、confusing和confusing()展示的都是正确的。
如果你说“发生”是指“被解析、编译和绑定”,那么是的,这确实是先发生的。我不太明白你想表达什么。我同意这是正确的——当然是正确的,这段代码是写过并运行过的,我发布的结果也是我得到的,所以它一定是正确的。我不明白__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()。
没错,你可以直接用内置的 type() 函数,它可以告诉你一个对象是什么类型的。比如,输入 type(clsObj) 会返回“实例”这个结果。你也可以用 isinstance 来检查一下。
如果你输入 isinstance(clsObj, Cls),它会返回 True,说明 clsObj 是 Cls 的一个实例。而如果你输入 isinstance(Cls, Cls),它会返回 False,表示 Cls 不是它自己的实例。