Python type()或_类_,==或是

Python type()或_类_,==或是,python,language-features,Python,Language Features,我想测试一个对象是否是一个类的实例,并且只测试这个类(没有子类)。我可以通过以下两种方式来实现: obj.__class__ == Foo obj.__class__ is Foo type(obj) == Foo type(obj) is Foo 有没有理由选择一个而不是另一个?(性能差异、陷阱等) 换句话说:a)使用\uuu class\uuu和类型(x)之间有实际区别吗?b) 使用is比较类对象是否总是安全的 更新:谢谢大家的反馈。我仍然对类对象是否是单例对象感到困惑,我的常识是它们是

我想测试一个对象是否是一个类的实例,并且只测试这个类(没有子类)。我可以通过以下两种方式来实现:

obj.__class__ == Foo
obj.__class__ is Foo
type(obj) == Foo
type(obj) is Foo
有没有理由选择一个而不是另一个?(性能差异、陷阱等)

换句话说:a)使用
\uuu class\uuu
类型(x)
之间有实际区别吗?b) 使用
is
比较类对象是否总是安全的


更新:谢谢大家的反馈。我仍然对类对象是否是单例对象感到困惑,我的常识是它们是单例对象,但要得到确认真的很难(试着在谷歌上搜索“python”、“class”和“unique”或“singleton”)

我还想澄清的是,对于我的特殊需求,“更便宜”的解决方案是最好的,因为我正在尝试优化少数几个专门类中的大部分(几乎达到了明智的做法是放弃Python并用C开发特定模块的地步)。但这个问题背后的原因是为了更好地理解这种语言,因为它的一些特征对我来说太模糊了,不容易找到这些信息。这就是为什么我让讨论稍微扩展一点,而不是满足于
\uuuu class\uuuuuu is
,这样我就可以听到更有经验的人的意见。到目前为止,这是非常有成效的

我运行了一个小测试来测试4个备选方案的性能。分析器的结果是:

               Python  PyPy (4x)
type()    is   2.138   2.594
__class__ is   2.185   2.437
type()    ==   2.213   2.625
__class__ ==   2.271   2.453
毫不奇怪,
在所有情况下都比
=
表现得更好
type()
在Python中的性能更好(快2%),在PyPy中的性能更好(快6%)。有趣的是,在PyPy中,
\uuuu类
的性能比
type()更好


更新2:许多人似乎不明白我所说的“类是单体”是什么意思,所以我将用一个例子来说明:

>>> class Foo(object): pass
...
>>> X = Foo
>>> class Foo(object): pass
...
>>> X == Foo
False
>>> isinstance(X(), Foo)
False
>>> isinstance(Foo(), X)
False

>>> x = type('Foo', (object,), dict())
>>> y = type('Foo', (object,), dict())
>>> x == y
False
>>> isinstance(x(), y)
False

>>> y = copy.copy(x)
>>> x == y
True
>>> x is y
True
>>> isinstance(x(), y)
True
>>> y = copy.deepcopy(x)
>>> x == y
True
>>> x is y
True
>>> isinstance(x(), y)
True
如果有N个
type
类型的对象,这无关紧要,给定一个对象,只有一个对象是它的类,因此在这种情况下比较以供参考是安全的。由于引用比较总是比值比较便宜,我想知道我上面的断言是否成立。我得出的结论是,除非有人提出相反的证据。

类型()
的结果相当于
obj.\uu class\uuu
在新样式的类中,使用
is
比较类对象是不安全的,请改用
=

对于新样式类这里更可取的方法是
type(obj)==Foo

正如MichaelHoffman在他的回答中指出的那样,新的和旧的样式类之间存在差异,因此对于向后兼容的代码,您可能需要使用
obj.\uuuu class\uuuu==Foo

<>对于那些声称<代码>实例(Objo,FoO)< /> >的人来说,最好考虑下面的场景:

class Foo(object):
    pass

class Bar(Foo):
    pass

>>> obj = Bar()
>>> isinstance(obj, Foo)
True
>>> type(obj) == Foo
False

OP希望
type(obj)=Foo
的行为为假,即使
Foo
Bar
的基类

is
只能用于身份检查,而不是类型检查(规则中有一个例外,您可以并且应该使用
is
来检查单身人士)


注意:我通常也不会使用
类型
==
进行类型检查。类型检查的首选方法是
isinstance(obj,Foo)
。如果您有理由检查某个对象是否不是子类实例,那么我觉得它的设计很可疑。当
类Foo(Bar):
时,则
Bar
是一个
Foo
,您应该避免代码的某些部分必须在
Foo
实例上工作,但在
Bar
实例上中断的情况

对于旧式类,有一个区别:

>>X级:通过
... 
>>>类型(X)
>>>X.。_u类__
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:类X没有属性“\uuuuuu class\uuuuuuuuuuuuuuu”
>>>x=x()
>>>x.。_u类__
>>>类型(x)
新型班级的重点是统一班级和类型。从技术上讲,
\uuuuuuuuuuuuuuuuuuu类
是唯一既适用于新样式类实例又适用于旧样式类实例的解决方案,但它也会在旧样式类对象本身上引发异常。您可以对任何对象调用
type()
,但不是每个对象都有
\uuuu类
。另外,你可以用一种你不能用
type()
乱搞的方式来乱搞
\uuuu class\uuu

>>Z类(对象):
...     def uu getattribute_uu(self,name):
...             返回“火腿”
... 
>>>z=z()
>>>z.。_u类__
“火腿”
>>>类型(z)
就个人而言,我通常有一个只包含新样式类的环境,而且作为一种样式,我更喜欢使用
type()
,因为我通常更喜欢存在的内置函数,而不是使用魔法属性。例如,我也更喜欢
bool(x)
而不是
x.\uu非零\uuu()

更新:谢谢大家的反馈。我仍然对类对象是否是单例对象感到困惑,我的常识是它们是单例对象,但要得到确认真的很难(试着在谷歌上搜索“python”、“class”和“unique”或“singleton”)

我可以确认
\uuuu instance\uuuu
是一个单例。这是证据

>>> t1=File.test()
made class
>>> t2=File.test()
made class
>>> print t1.__class__()
made class
<File.test object at 0x1101bdd10>
>>> print t2.__class__()
made class
<File.test object at 0x1101bdd10>
只有在使用
类“名称”(对象):
时,才存在
\uuuu实例\uuuu
方法。如果使用经典样式的类,
class“name”:
,则
\uuuuu实例\uuuu
方法不存在


这意味着你可能要使用最通用的
类型
,除非你知道事实实例确实存在。

对。如果你不能做到这一点,你通常有一个坏的设计。顺便说一句,我同意我的设计不是最好的,但我写了一些非常专业的类,需要优化的空间,而不是我
>>> print t1
<File.test object at 0x1101bdc90>
>>> print t2
<File.test object at 0x1101bdcd0>