mgi*_*nbr 47 python language-features
我想测试一个对象是否是一个类的实例,并且只测试这个类(没有子类).我可以这样做:
obj.__class__ == Foo
obj.__class__ is Foo
type(obj) == Foo
type(obj) is Foo
Run Code Online (Sandbox Code Playgroud)
是否有理由选择一个而不是另一个?(业绩差异,陷阱等)
换句话说:a)使用__class__和type(x)?之间有什么实际区别吗?b)类对象总是可以安全地进行比较is吗?
更新:感谢大家的反馈.我仍然对类对象是否是单身人士感到困惑,我的常识说他们是,但是很难得到确认(尝试谷歌搜索"python","class"和"unique"或"singleton") .
我还要澄清一点,根据我的特殊需求,"更便宜"的解决方案才是最好的,因为我正在尝试优化一些专业课程中的大部分(几乎达到了理智的程度)要做的是删除Python并在C)中开发该特定模块.但问题背后的原因是为了更好地理解语言,因为它的某些功能对于我来说很容易找到这些信息.这就是为什么我让讨论延伸一点而不是解决__class__ 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
Run Code Online (Sandbox Code Playgroud)
不出所料,is表现优于==所有情况.type()在Python中表现更好(2%更快)并且__class__在PyPy中表现更好(快6%).有趣的是,__class__ ==在PyPy 中表现更好type() is.
更新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
Run Code Online (Sandbox Code Playgroud)
如果存在N个类型type的对象并不重要,给定一个对象,只有一个将是它的类,因此在这种情况下比较引用是安全的.由于参考比较总是比价值比较便宜,我想知道我的断言是否成立.我得出的结论是,除非有人提出相反的证据.
Mic*_*man 32
对于旧式课程,有一个区别:
>>> class X: pass
...
>>> type(X)
<type 'classobj'>
>>> X.__class__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class X has no attribute '__class__'
>>> x = X()
>>> x.__class__
<class __main__.X at 0x171b5d50>
>>> type(x)
<type 'instance'>
Run Code Online (Sandbox Code Playgroud)
新式课程的重点是统一课程和类型.从技术上讲,__class__它是唯一适用于新旧类实例的解决方案,但它也会在旧式类对象本身上引发异常.您可以调用type()任何对象,但不是每个对象都有__class__.此外,你可以用你不能捣乱__class__的方式捣乱type().
>>> class Z(object):
... def __getattribute__(self, name):
... return "ham"
...
>>> z = Z()
>>> z.__class__
'ham'
>>> type(z)
<class '__main__.Z'>
Run Code Online (Sandbox Code Playgroud)
就个人而言,我通常只有一个新风格的环境,并且type()由于我喜欢使用内置函数,因此我喜欢使用魔术属性.举例来说,我也宁愿bool(x)到x.__nonzero__().
And*_*ark 12
结果type()等同obj.__class__于新样式类,并且类对象不能安全地进行比较使用is,==而是使用.
对于新风格的类,这里更好的方式是type(obj) == Foo.
正如Michael Hoffman在他的回答中指出的那样,新旧类型之间存在差异,因此对于可能需要使用的向后兼容代码obj.__class__ == Foo.
对于声称isinstance(obj, Foo)更可取的人,请考虑以下情形:
class Foo(object):
pass
class Bar(Foo):
pass
>>> obj = Bar()
>>> isinstance(obj, Foo)
True
>>> type(obj) == Foo
False
Run Code Online (Sandbox Code Playgroud)
OP想要行为type(obj) == Foo,即使它Foo是基类,它也会是假的Bar.
wim*_*wim 12
is应该只用于身份检查,而不是类型检查(规则中有一个例外情况,您可以并且应该用它is来检查单身人士).
注意:我通常也不会使用type和==进行类型检查.类型检查的首选方法是isinstance(obj, Foo).如果你有理由检查某些东西是不是一个子类实例,它对我来说就像一个腥味的设计.什么时候class Foo(Bar):,然后Bar 是 Foo,你应该避免任何情况,你的代码的某些部分必须在一个Foo实例上工作,但在一个Bar实例上中断.
| 归档时间: |
|
| 查看次数: |
15478 次 |
| 最近记录: |