2016-08-24 4 views
0

사용자 지정 루프 동작을 구현 중입니다. 루프 입력, 모든 루프 시작, 모든 루프 끝 및 루프 영역 끝내기가 필요합니다. 지금까지이 파이썬 (2.7)에서 아름답게 간단하다 :중단 후 사용자 정의 반복기 또는 생성기

def my_for(loop_iterable): 
    enter_loop() 
    for i in loop_iterable: 
     loop_start() 
     yield i 
     loop_end() 
    exit_loop() 

for i in my_for([1, 2, 3]): 
    print "i: ", i 
    if i == 2: 
     break 

난 데 문제는 break 후 실행 loop_end()exit_loop()을 받고입니다. 나는 사용자가 휴식 시간 전에 삽입해야 다른 함수를 정의하여이 문제를 해결 한 :

def break_loop(): 
    loop_end() 
    exit_loop() 

for i in my_for([1, 2, 3]): 
    print "i: ", i 
    if i == 2: 
     break_loop() 
     break 

하지만 정말 줄을 추가하는 것을 기억해야 사용자가 할 수 있지 싶습니다. 제 생각에는 반복기 클래스로 생성기 함수를 다시 작성한다면 아마도 break에 코드를 실행하는 방법이 있을까요?

덧붙여 말하자면, continue은 그대로 정상적으로 작동합니다!

+0

왜 사용자 정의 루프 동작을 구현하고 있습니까? – Blender

답변

0

당신이 사용할 수있는 context manager :

class Looper(object): 
    def __init__(self, iterable): 
     self.iterable = iterable 
     self.need_to_end = False 

    def __enter__(self): 
     return self 

    def __exit__(self, exception_type, exception_value, traceback): 
     self.exit_loop() 
     # Handle exceptions or swallow them by returning True 

    def enter_loop(self): 
     print 'enter_loop' 

    def loop_start(self): 
     self.need_to_end = True 
     print 'loop_start' 

    def loop_end(self): 
     self.need_to_end = False 
     print 'loop_end' 

    def exit_loop(self): 
     if self.need_to_end: 
      self.loop_end() 

     print 'exit_loop' 

    def __iter__(self): 
     self.enter_loop() 

     for i in self.iterable: 
      self.loop_start() 
      yield i 
      self.loop_end() 

귀하의 코드가 조금 더 얻을 것입니다,하지만 당신은 더 깨끗하게 예외 및 다른 것들을 처리 할 수 ​​있습니다

with Looper([1, 2, 3, 4, 5, 6]) as loop: 
    for i in loop: 
     print i 

     if i == 2: 
      continue 
     elif i == 3: 
      break 

그것은 당신이 원하는만큼 작동 예상 :

enter_loop 
loop_start 
1 
loop_end 
loop_start 
2 
loop_end 
loop_start 
3 
loop_end 
exit_loop 
+0

고마워요! 'self.exited' 속성을 추가하면 iterator의 끝에있는 exit_loop()을 호출하여 (내가 가지고있는 생성기로 사용) 조건부로'exit_loop()'를 호출 할 수 있습니다 (__exit __() '여전히 컨텍스트 관리가 가능합니다. 매력처럼 작동합니다! 나는 그것을 할 수있는 두 가지 방법을 제공 할 것입니다. –

0

클래스에서 정의하여 __enter____exit__ 매직 기능을 사용할 수 있습니다. 전화를 걸려면 with과 함께 사용할 수 있습니다. with 블록 내에서 코드를 실행하기 전에 __enter__ 메서드가 호출되고 with 블록이 종료 될 때 __exit__ 함수가 호출됩니다. 예를 들어 : 반복자로 만들기 위해 지금

>>> class MyTestWrapper(object): 
...  def __enter__(self): 
...   print 'I am in __enter__' 
...  def __exit__(self, type, value, traceback): 
...   print 'I am in __exit__' 
... 
>>> with MyTestWrapper() as s: 
...  print 'My Loop Logic' 
... 
I am in __enter__ 
My Loop Logic 
I am in __exit__ 

, 당신은 __iter__ 함수를 정의해야합니다. 이것을 사용하여 iterator로 부를 수 있습니다. 업데이트 된 코드는 다음과 같습니다

>>> class MyIterator(object): 
...  def __init__(self, iterable): 
...   self.iterable = iterable 
...   self.need_to_end = False 
...  def __enter__(self): 
...   print 'I am in __enter__' 
...   return self 
...  def __exit__(self, type, value, traceback): 
...   self.loop_end() 
...   print 'I am in __exit__' 
...  def loop_start(self): 
...   self.need_to_end = True 
...   print 'Starting Loop . . . ' 
...  def loop_end(self): 
...   self.need_to_end = False 
...   print 'Ending Loop . . . ' 
...  def __iter__(self): 
...   for i in self.iterable: 
...    self.loop_start() 
...    yield i 
...    self.loop_end() 
... 
>>> with MyIterator([1,2,3, 4]) as my_iterator: 
...  for i in my_iterator: 
...   print 'I am: ', i 
...   if i == 2: 
...    break 
... 
I am in __enter__ 
Starting Loop . . . 
I am: 1 
Ending Loop . . . 
Starting Loop . . . 
I am: 2 
Ending Loop . . . 
I am in __exit__ 

는 이들과 다른 붙박이 기능에 대한 자세한 내용은 Python's Context Manager를 참조하십시오.

관련 문제