Как вернуться к определенной точке цикла for?

У меня есть ряд вложенных циклов, которые циклически перебирают несколько файлов Excel и на основе проверок содержимого добавляют содержимое в список фреймов данных.

При определенном условии мне нужно выйти из текущего цикла, не добавлять в список фреймов данных и продолжить синтаксический анализ следующего excel. К сожалению, я не могу понять, как настроить цикл, чтобы добиться желаемого поведения.

В настоящее время код выглядит следующим образом. Я добавил комментарии, объясняющие, какое поведение я ищу.

for name in folder_names:
path = rf'I:\PATH\{name}'
file_list = [f for f in glob.glob(path+"/*.xlsx")]
df_list = []
for f in file_list: #if a break event is triggered, I need to return here.
    xl = pd.ExcelFile(f)
    if len(xl.sheet_names) == 1:
        wb = load_workbook(f, data_only = True)
        sh = wb.worksheets[0]
        ColNames = {}
        Current  = 0
        for COL in sh.iter_cols(1, sh.max_column):
            ColNames[COL[0].value] = Current
            Current += 1
        for row_cells in sh.iter_rows(min_row=2, max_row=len(sh['D'])):
            if row_cells[ColNames['XXXX ID']].fill.start_color.index != '00000000':
                path_file.write(f+'\n') 
                break                
        df_list.append(pd.read_excel(f)) #if a break event is triggered, I need this line to NOT be executed

Желаемая логика:

Если текущий excel имеет только 1 лист, проверьте, не имеет ли столбец D цвет заливки ячейки, если true, добавьте в список фреймов данных, если false, вернитесь к следующему файлу excel в цикле.

Вам понадобится флаг, потому что break завершает только внутренний цикл. Что-то вроде keep_file = True, затем в перерыве используйте keep_file = False, и вы можете поместить свою команду добавления в блок if keep_file. Или теперь, когда вы находитесь вне цикла, вы можете сделать if not keep_file: continue, который переходит к следующей итерации вашего for

RufusVS 09.12.2020 22:27

@RufusVS Заявление for ... else ... сделает эту работу. Просто пропустите добавление, если мы нажмем break. Так было бы else: df_list.append(...) и все.

Asocia 09.12.2020 22:31

@Asocia Спасибо! Я никогда не использовал конструкцию for..else в Python, и мне казалось, что здесь она сработает. Но так как я никогда им не пользовался, я не был уверен.

RufusVS 09.12.2020 22:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
117
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете добавить логическое значение, чтобы проверить, вышли ли вы из цикла или нет. Это должно выглядеть примерно так (не стесняйтесь менять логическое имя):

for name in folder_names:
    path = rf'I:\PATH\{name}'
    file_list = [f for f in glob.glob(path+"/*.xlsx")]
    df_list = []
    for f in file_list: #if a break event is triggered, I need to return here.
        xl = pd.ExcelFile(f)
        if len(xl.sheet_names) == 1:
            wb = load_workbook(f, data_only = True)
            sh = wb.worksheets[0]
            ColNames = {}
            Current  = 0
            loop_broken = False
            for COL in sh.iter_cols(1, sh.max_column):
                ColNames[COL[0].value] = Current
                Current += 1
            for row_cells in sh.iter_rows(min_row=2, max_row=len(sh['D'])):
                if row_cells[ColNames['XXXX ID']].fill.start_color.index != '00000000':
                    path_file.write(f+'\n') 
                    loop_broken = True
                    break                
            if (not loop_broken): df_list.append(pd.read_excel(f)) #if a break event is triggered, I need this line to NOT be executed

добавление флага решит это:

flag = False
for x in range(10):
    if x == 2:
        flag = True
        break
if flag:
     # dont do sth
     pass
else:
     # do sth
     pass

Вы можете написать заявление for ... else ....

for i in range(5):
    print(i)
    if i > 2:
        print("Hit break")
        break
else:
    print("I didn't hit a break inside the loop")
0
1
2
3
Hit break
for i in range(5):
    print(i)
    if i > 2:
        pass
else:
    print("I didn't hit a break inside the loop")
0
1
2
3
4
I didn't hit a break inside the loop

Итак, чтобы ответить на ваш вопрос, вам просто нужно сделать это:

...
for row_cells in sh.iter_rows(min_row=2, max_row=len(sh['D'])):
    if row_cells[ColNames['XXXX ID']].fill.start_color.index != '00000000':
        path_file.write(f+'\n') 
        break
else: # <- add this line and indent your code
    df_list.append(pd.read_excel(f))

Другие вопросы по теме