为什么PEP-343在这种情况下使用type()?使用类型()进行方法调用
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
我们能不能就如用exit = mgr.__exit__
和value = mgr.__enter__()
?似乎对我来说更简单,但我认为我错过了一些东西。
为什么PEP-343在这种情况下使用type()?使用类型()进行方法调用
mgr = (EXPR)
exit = type(mgr).__exit__ # Not calling it yet
value = type(mgr).__enter__(mgr)
我们能不能就如用exit = mgr.__exit__
和value = mgr.__enter__()
?似乎对我来说更简单,但我认为我错过了一些东西。
当然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__()
。
上述构建体得到mgr
对象的类型(类)的未结合方法,否则mgr
字典被acessed,你会得到结合的方法。
好吧,所以这只是一个约定,如果有人更改实例__dict__,我们仍然会调用原始函数。甚至没有想到 - 还没有找到我想要这样做的情况;)但是如果有人这样做,会导致一些奇怪的行为,所以它是有道理的。 – Voo
@Voo:约定的基本原理并不是避免奇怪的行为 - 你仍然可以用实时类型'a'覆盖它的类型来覆盖实例'a'的'__add __()'方法。 __class__ = type(“”,(type(a),),{“__add__”:lambda self,other:42})'。相反,这种行为的基本原理是性能。特殊的方法不会在类型的'__dict__'中查找。内部类型数据结构提供了指向特殊方法的特殊字段,因此可以更快地查找它们,请参阅http://docs.python.org/extending/newtypes.html#the-basics。 –
你的意思是PyMethodDef数组 - 它仍然需要通过搜索(但可能会更快?)?还是这样做是为了让所有特殊方法都使用一个通用方法,因为有些方法(如tp_iternext)会从中获利,因为这些方法是在PyTypeObject中声明的? – Voo