2011-03-14 9 views
3

이해할 수 있듯이 __iter__ 메서드를 사용하여 반복기를 반환하는 개체에 for 루프 구성을 사용할 수 있습니다.파이썬 __iter__ 및 for 루프

def __getattribute__(self,name): 
    if name in ["read","readlines","readline","seek","__iter__","closed","fileno","flush","mode","tell","truncate","write","writelines","xreadlines"]: 
     return getattr(self.file,name) 
    return object.__getattribute__(self,name) 

내가 a이되는 다음과 같은 상황이 발생,이 클래스의 객체를 가지고 :

>>> hasattr(a,"__iter__") 
True 
>>> for l in a: print l 
... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'TmpFile' object is not iterable 
>>> for l in a.file: print l 
... 
>>> 

그래서 파이썬은 a__iter__을 가지고보고 난 다음 __getattribute__ 메소드를 구현하는 객체를 가지고 메서드를 호출하지만 iterable이라고는 생각하지 않습니다. 나는 무엇을 잘못 했는가? 이것은 파이썬 2.6.4와 같습니다.

답변

12

진행중인 미묘한 구현 정보가 있습니다. __iter__은 실제로 인스턴스 메소드가 아니라 클래스 메소드입니다. 즉 obj.__iter__() 대신 obj.__class__.__iter__(obj)이 호출됩니다.

이것은 후드 아래의 슬롯 최적화로 인해 Python 런타임이 반복자를 더 빠르게 설정할 수 있기 때문입니다. 이터레이터는 가능한 한 빨리 수행해야하므로 매우 중요합니다.

기본 class 유형에 __getattribute__을 정의 할 수 없으므로이 방법을 동적으로 반환 할 수 없습니다. 이는 대부분 __metamethods__에 적용됩니다. 실제 래퍼를 작성해야합니다.

+1

일을 ... 그들이 말하는대로, 당신은 매일 새로운 것을 배웁니다. :) – delnan

+0

+1 그리고 어떤 delnan이 말하는지. – slezica

+0

적어도 CPython에서이 부작용을 볼 수 있습니다 :'__getattribute__'를 정의하면'iter'를 사용할 때'__class__'가 호출된다는 것을 알게 될 것입니다. 런타임은 '__iter__ '를 호출하는 객체의 클래스. (이것은 구현 세부 사항으로 간주되어야합니다.) –

4

특수 메서드 중 일부는 클래스를 만들 때 최적화되므로 나중에 추가하거나 할당하여 재정의 할 수 없습니다.

이 방법은 여전히 ​​우회 할 수 언어 구문 또는 내장 함수를 통해 암시 적 호출의 결과로 특별한 방법을 찾을 때 : 말한다 __getattribute__에 대한 documentation 참조하십시오.

은 당신이이 경우에 할 필요하면 전화를 전달 __iter__의 직접적인 구현을 제공 할 수 있습니다 :`iter`는`__getattribute__`를 호출하지 않습니다 그 이유는 그래서

def __iter__(self): 
    return self.file.__iter__()