Как можно сократить и усовершенствовать код Python?

Не могу понять, как можно избавиться от дублирования кода. continue не дает вынести в метод.

def main():
    accounts = file_to_string_array('data.txt')
    accounts = string_array_to_array(accounts)
    updated_data = accounts
    for i, account in enumerate(accounts):

        if account[8] == 'Yes':
            continue

        imap = imaplib.IMAP4_SSL('imap.mail.ru')
        imap.login(account[1], account[4])
        link = find_link(imap, 'INBOX')
        if link == '':
            link = find_link(imap, '&BCEEPwQwBDw-')
            if link == '':
                continue

        open_link(link, sleep_duration=5)

        imap.close()
        imap.logout()

        imap = imaplib.IMAP4_SSL('imap.mail.ru')
        imap.login(account[1], account[4])
        link = find_link(imap, 'INBOX')
        if link == '':
            link = find_link(imap, '&BCEEPwQwBDw-')
            if link == '':
                continue

        open_link(link, sleep_duration=1)

        imap.close()
        imap.logout()

        updated_data[i][7] = 'Yes'
        updated_data[i][8] = 'Yes'

    update_data(updated_data)

Ответы (2 шт):

Автор решения: Paganini

Вынести в функцию

def foo(link):
   if link == '':
      link = find_link(imap, '&BCEEPwQwBDw-')
      if link == '':
          return true
   return link

Делать continue, если результат функции - true

if foo(link) == true:
   continue
→ Ссылка
Автор решения: gil9red
  1. Код с поиском ссылки

    link = find_link(imap, 'INBOX')
    if link == '':
        link = find_link(imap, '&BCEEPwQwBDw-')
        if link == '':
            continue
    

    Я бы лучше заменил на функцию:

    def get_link(imap: imaplib.IMAP4_SSL, search_in1: str, search_in2: str) -> str:
        link = find_link(imap, search_in1)
        if not link:
            link = find_link(imap, search_in2)
        return link
    

    Аналогично через оператор or:

    def get_link(imap: imaplib.IMAP4_SSL, search_in1: str, search_in2: str) -> str:
        return find_link(imap, search_in1) or find_link(imap, search_in2)
    
  2. Не хорошо два раза создавать подключение к почте и закрывать, мне кажется лучше один раз сделать, а после закрыть через try/finally. Даже если будет вызван continue, код в finally выполнится, поэтому мы будем уверены, что соединение с почтовым сервером будет правильно закрыто

  3. UPD. уточнение пункта 2, можно через контекстный менеджер открывать, тогда и try/finally с закрытием сессии не понадобится

Итого:

import imaplib


def get_link(imap: imaplib.IMAP4_SSL, search_in1: str, search_in2: str) -> str:
    link = find_link(imap, search_in1)
    if not link:
        link = find_link(imap, search_in2)
    return link


def main():
    accounts = file_to_string_array('data.txt')
    accounts = string_array_to_array(accounts)
    updated_data = accounts
    for i, account in enumerate(accounts):
        if account[8] == 'Yes':
            continue

        with imaplib.IMAP4_SSL('imap.mail.ru') as imap:
            imap.login(account[1], account[4])
            
            link = get_link(imap, 'INBOX', '&BCEEPwQwBDw-')
            if not link:
                continue
            open_link(link, sleep_duration=5)

            link = get_link(imap, 'INBOX', '&BCEEPwQwBDw-')
            if not link:
                continue
            open_link(link, sleep_duration=1)

        updated_data[i][7] = 'Yes'
        updated_data[i][8] = 'Yes'

    update_data(updated_data)
→ Ссылка