2015-03-09 7 views
1

У меня есть ниже код работает в Python 2.7х:Побег из вложенного цикла в Python

def captureAlbumLinks(): 
    for page in index_pages: # index_pages is a list of URLs 
     resp = connect_tor(page) 
     soup = BeautifulSoup(resp.read(), from_encoding=resp.info().getparam('charset')) 
     try: 
      # The below two variables relate to URLs of type string 
      x = pickle.load(open("last_passworded_album.p", "rb")) 
      y = pickle.load(open("last_accessible_album.p", "rb")) 
     except: 
      print "There is no pickle file" 
     for a in soup.find_all('a', href=True): 
      if (root_url + a['href']) == x or (root_url) + a['href'] == y: 
       break 
      elif "passchk.php" in a['href']: 
       passworded_albums.append(root_url + a['href']) 
      elif "search.php" in a['href'] or "switch.php" in a['href']: 
       pass 
      else: 
       if ".html" in a['href']: 
        accessible_albums.append(root_url + a['href']) 

В сущности, «если (root_url + а [ 'HREF']) == х или (root_url) + a ['href'] == y: ", я не хочу, чтобы какой-либо из elifs запускался и хотел выйти из 'для цикла'. Тем не менее, даже если существует оператор if, выполняется true (проверено с помощью оператора печати), мой код, похоже, запускается на следующий «elif». Я думаю, что на данный момент я просто ломаюсь от цикла «if», а не цикла «for».

Я чувствую, что это проблема с отступом, но попытался переместить «перерыв», но без радости.

Может ли кто-нибудь помочь?

+2

он идет в elif, потому что ваш, если никогда не оценивает True, что такое x и y? я бы также предложил распечатать 'root_url + a ['href'])' –

+1

Вы говорите «вложенные циклы», я вижу только один ... 'break' не имеет взаимодействия с операторами' if', если этот блок работает, если будет вырваться из этого цикла 'for'. –

+0

Спасибо Padraic. X и Y по сути являются URL-адресами, которые будут соответствовать строке, образованной «root_url» + a ['href'] – thefragileomen

ответ

1

Вы можете просто вернуться в конце функции:

import pickle 
def capture_album_links(): 
    for page in index_pages: # index_pages is a list of URLs 
     resp = connect_tor(page) 
     soup = BeautifulSoup(resp.read(), from_encoding=resp.info().getparam('charset')) 
     try: 
      # with will automatically close your files 
      with open("last_passworded_album.p", "rb") as f1, open("last_accessible_album.p", "rb") as f2: 
       x = pickle.load(f1) 
       y = pickle.load(f2) 
     # catch specific errors 
     except (pickle.UnpicklingError,IOError) as e: 
      print(e) 
      print "There is no pickle file" 
      # continue on error or x and y won't be defined 
      continue 
     for a in soup.find_all('a', href=True): 
      if root_url + a['href'] in {x, y}: 
       return # just return to end both loops 
      elif "passchk.php" in a['href']: 
       passworded_albums.append(root_url + a['href']) 
      elif "search.php" in a['href'] or "switch.php" in a['href']: 
       continue 
      else: 
       if ".html" in a['href']: 
        accessible_albums.append(root_url + a['href']) 
0

Редактировать: Подавленный бесполезный комментарий. Добавление альтернативы:

Помимо использования возврата, в тех случаях, когда вы хотите сделать что-то после цикла вы можете использовать либо исключение:

class MyException(Exception): 
    pass 

def captureAlbumLinks(): 
    try: 
     for page in index_pages: # index_pages is a list of URLs 
      resp = connect_tor(page) 
      soup = BeautifulSoup(resp.read(), from_encoding=resp.info().getparam('charset')) 
      try: 
       # The below two variables relate to URLs of type string 
       x = pickle.load(open("last_passworded_album.p", "rb")) 
       y = pickle.load(open("last_accessible_album.p", "rb")) 
      except: 
       print "There is no pickle file" 
      for a in soup.find_all('a', href=True): 
       if (root_url + a['href']) == x or (root_url + a['href']) == y: 
        raise MyException() 
       elif "passchk.php" in a['href']: 
        passworded_albums.append(root_url + a['href']) 
       elif "search.php" in a['href'] or "switch.php" in a['href']: 
        pass 
       else: 
        if ".html" in a['href']: 
         accessible_albums.append(root_url + a['href']) 
    except MyException as e: 
     pass 

Другой подход, который может быть менее интуитивное, чтобы использовать else пункт в for петлях, которая выполняется только тогда, когда for останавливается нормально (и если вы не break из него):

def captureAlbumLinks(): 
    for page in index_pages: # index_pages is a list of URLs 
     resp = connect_tor(page) 
     soup = BeautifulSoup(resp.read(), from_encoding=resp.info().getparam('charset')) 
     try: 
      # The below two variables relate to URLs of type string 
      x = pickle.load(open("last_passworded_album.p", "rb")) 
      y = pickle.load(open("last_accessible_album.p", "rb")) 
     except: 
      print "There is no pickle file" 
     for a in soup.find_all('a', href=True): 
      if (root_url + a['href']) == x or (root_url + a['href']) == y: 
       break 
      elif "passchk.php" in a['href']: 
       passworded_albums.append(root_url + a['href']) 
      elif "search.php" in a['href'] or "switch.php" in a['href']: 
       pass 
      else: 
       if ".html" in a['href']: 
        accessible_albums.append(root_url + a['href']) 
     else: 
      continue 
     break 
+0

Я не понимаю нисходящее. 'break' - это правильное решение, если автор хочет выйти из цикла (' return', как было предложено в комментарии выше, является излишним), поэтому я пытаюсь спросить, не выходит ли проблема из самого теста , (Комментирование невозможно, так как у меня еще недостаточно кармы.) –

+0

как перерыв будет нарушать внешний цикл? Параны также не имеют значения –

+0

А, когда я написал свое первое сообщение, был всего один цикл (я, по-видимому, медленно писал), теперь ясно, извините. Однако, я считаю, что пользовательское исключение было бы чуть более общим, чем просто возвращение. –

1

порой практический подход, чтобы обернуть его в FUNC и возвращение. В вашем случае вы можете просто «вернуть», но в общем, вы бы написать внутреннюю функцию (в данном случае «петля»)

def captureAlbumLinks(): 
    def loops(): 
    for page in index_pages: # index_pages is a list of URLs 
     resp = connect_tor(page) 
     soup = BeautifulSoup(resp.read(), from_encoding=resp.info().getparam('charset')) 
     try: 
      # The below two variables relate to URLs of type string 
      x = pickle.load(open("last_passworded_album.p", "rb")) 
      y = pickle.load(open("last_accessible_album.p", "rb")) 
     except: 
      print "There is no pickle file" 
     for a in soup.find_all('a', href=True): 
      if (root_url + a['href']) == x or (root_url) + a['href'] == y: 
       return 
      elif "passchk.php" in a['href']: 
       passworded_albums.append(root_url + a['href']) 
      elif "search.php" in a['href'] or "switch.php" in a['href']: 
       pass 
      else: 
       if ".html" in a['href']: 
        accessible_albums.append(root_url + a['href']) 
    return loops() 
1

Мне нравится рефактор в функцию и возвращаюсь. Вы также можете поместить код в блок try/except и создать исключение, если хотите отключить все циклы.

Смежные вопросы