2011-08-01 39 views
2

为什么PEP-343在这种情况下使用type()?使用类型()进行方法调用

mgr = (EXPR) 
    exit = type(mgr).__exit__ # Not calling it yet 
    value = type(mgr).__enter__(mgr) 

我们能不能就如用exit = mgr.__exit__value = mgr.__enter__()?似乎对我来说更简单,但我认为我错过了一些东西。

回答

5

当然PEP 可能使用来使用实例本身的属性而不是类型的属性,但这与在Python中使用特殊方法相反。例如

a + b 

被转换为

type(a).__add__(a, b) 

a.__add__(b) 

如由以下示例:

>>> class MyInt(int): 
...  pass 
... 
>>> a = MyInt(3) 
>>> b = MyInt(4) 
>>> a + b 
7 
>>> a.__add__ = lambda self, other: 42 
>>> a + b 
7 

所以,叔o与Python的其余部分保持一致,首先应在类型字典中查找特殊方法__enter__()__exit__()

+0

好吧,所以这只是一个约定,如果有人更改实例__dict__,我们仍然会调用原始函数。甚至没有想到 - 还没有找到我想要这样做的情况;)但是如果有人这样做,会导致一些奇怪的行为,所以它是有道理的。 – Voo

+1

@Voo:约定的基本原理并不是避免奇怪的行为 - 你仍然可以用实时类型'a'覆盖它的类型来覆盖实例'a'的'__add __()'方法。 __class__ = type(“”,(type(a),),{“__add__”:lambda self,other:42})'。相反,这种行为的基本原理是性能。特殊的方法不会在类型的'__dict__'中查找。内部类型数据结构提供了指向特殊方法的特殊字段,因此可以更快地查找它们,请参阅http://docs.python.org/extending/newtypes.html#the-basics。 –

+0

你的意思是PyMethodDef数组 - 它仍然需要通过搜索(但可能会更快?)?还是这样做是为了让所有特殊方法都使用一个通用方法,因为有些方法(如tp_iternext)会从中获利,因为这些方法是在PyTypeObject中声明的? – Voo

2

上述构建体得到mgr对象的类型(类)的未结合方法,否则mgr字典被acessed,你会得到结合的方法。

相关问题