2017-04-11 26 views
9

如果我定義了__iter__方法如下,它不會工作:爲什麼`__iter__`在定義爲實例變量時不起作用?

class A: 

    def __init__(self): 
     self.__iter__ = lambda: iter('text') 


for i in A().__iter__(): 
    print(i) 

iter(A()) 

結果:

t 
e 
x 
t 
Traceback (most recent call last): 
    File "...\mytest.py", line 10, in <module> 
    iter(A()) 
TypeError: 'A' object is not iterable 

正如你所看到的,調用A().__iter__()作品,但A()不迭代。

但是,如果我定義爲__iter__類,那麼它會工作:

class A: 

    def __init__(self): 

     self.__class__.__iter__ = staticmethod(lambda: iter('text')) 
     # or: 
     # self.__class__.__iter__ = lambda s: iter('text') 


for i in A(): 
    print(i) 

iter(A()) 

# will print: 
# t 
# e 
# x 
# t 

有誰知道爲什麼Python已經被這樣設計?即爲什麼__iter__作爲實例變量不起作用?你不覺得它不直觀嗎?

+0

我想你試圖做的很不直觀,你爲什麼不重寫__iter__作爲一種方法? http://stackoverflow.com/questions/4019971/how-to-implement-iter-self-for-a-container-object-python – PyNico

+1

似乎是一種舊式vs新式的課堂問題。你的代碼不適用於新風格的類。 – timgeb

+0

@PyNico在我目前正在處理的特定情況下,我更喜歡在'__init__'內定義'__iter__',因爲它的實現取決於實例化參數。 – AXO

回答

5

這是通過設計完成的。你可以在這裏找到詳細的描述:https://docs.python.org/3/reference/datamodel.html#special-method-lookup

簡短的回答:必須在類對象本身上設置特殊的方法才能被解釋器一致地調用。

長的答案:背後的想法是加速知名建築。在你的例子中:

class A: 
    def __init__(self): 
     self.__iter__ = lambda: iter('text') 

你是否經常在現實生活中編寫這樣的代碼?所以,Python做了什麼 - 它跳過了實例的字典查詢,即iter(A())根本不會「看到」self.__iter__,在這種情況下實際上是self.__dict__['__iter__']

它也跳過所有的__getattribute__實例和元類查找獲得顯着的加速。

+0

我已經重寫了答案,使其更易於理解。請告訴你是否有任何問題,或者有什麼不清楚的地方。 –

+0

這可能也與爲什麼'(1,2,3)[2]'比直接調用'(1,2,3)快得多.__ getitem __(2)'(在後面的python裏面也會看到實例屬性)。很好的答案,非常感謝。 – AXO

相關問題