爲什麼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