在python中重做当前for循环的迭代。

问题描述 投票:0回答:1

所以,我正在做一个for循环来迭代一个报告列表,并且正在考虑如何在条件成立时重做当前的迭代。以下是我所做的

for report in reports:
    check_if_table_exists_in_SQL_DATABASE_for_report_name
    download_report_using_request_in_csv
    preprocess_file_to_change_it
    get_Column_names_from_csv_file
    if check_if_table_exists_in_SQL_DATABASE_for_report_name = False:# table doesnt exist in DB
        create table
    else
        if cols_in_sql_table != cols_in_Csv_file:
            drop_Current_table
            goto_Start_of_the_current_iteration #<<<<< **THIs is what i need help with**

所以你看,理想的情况下,最好的情况是一个goto语句,但我想这是不受欢迎的......所以检查什么是最好的方式来做到这一点。

python
1个回答
2
投票

for 循环本身并不支持这个功能,但我想你可以通过某种方式来实现。

def redoable(iterable): 
    do_redo = False 
    def redo():
        nonlocal do_redo 
        do_redo = True 
    for item in iterable: 
        yield redo, item 
        while do_redo: 
            do_redo = False 
            yield redo, item

那么你可以做这样的事情:

for redo, report in redoable(reports):
    check_if_table_exists_in_SQL_DATABASE_for_report_name
    download_report_using_request_in_csv
    preprocess_file_to_change_it
    get_Column_names_from_csv_file
    if check_if_table_exists_in_SQL_DATABASE_for_report_name = False:# table doesnt exist in DB
        create table
    else:
        if cols_in_sql_table != cols_in_Csv_file:
            drop_Current_table
            redo()

1
投票

你可以使用生成器 send 协议来创建一个重播所提供值的版本。

def repeatable(obj):
    for x in obj:
        y = yield x
        while y is not None:
            yield None  # this gets consumed by the call to `send`
            y = yield y

这里你可以使用 gen.send(val) 具备 gen 重复 val 在下一次迭代中。这是一个例子。

repeat = repeatable(range(5))
repeat_me = {2, 3}
for x in repeat:
    print(x)
    if x in repeat_me:
        repeat.send(x)  # replays `x` on the next iteration
        repeat_me.remove(x)

0
投票

听起来你想要一个额外的 for 循环嵌套到原来的循环中,以便在表中循环。

for report in reports:
    ...
    for table in get_tables_for_report(report):
        if cols_in_sql_table != cols_in_Csv_file:
            drop_table(table)
        else:
            break
    else:
        create_table()

0
投票

不管怎么说

for report in reports:
    doing interesting things
    if check_if_table_exists_in_SQL_DATABASE_for_report_name = False:
        create table
    else
        if cols_in_sql_table != cols_in_Csv_file:
            drop_Current_table
            reports.insert(0, None) # this

好吧,这将在列表的开头插入一个虚值。reports 而当 for 循环是为了转到下一个值,list也有点 "转移",我们得到的是同样的值。

这是一个方法,但不是最好的(评论的建议是把for转为while,我觉得是最好的);在列表的开头插入是有代价的(我们不能用 collections.deque 因为它不允许在循环时进行修改),但我觉得单行的改变很有趣 :)


0
投票

你可以使用 more_itertools.seekable 用于重复最后一个元素。要做到这一点,你需要指定 seekable(..., maxlen=1) 然后你可以使用 .seek(0) 来重复最近产生的元素。

from more_itertools import seekable

repeat = seekable(range(5), maxlen=1)
repeat_me = {2, 3}
for x in repeat:
    print(x)
    if x in repeat_me:
        repeat.seek(0)
        repeat_me.remove(x)

0
投票

你可以尝试把整个逻辑放在一个无限的while循环里,然后你的退出条件来脱离循环。

这只是一个伪代码

exit_flag=True
While True:
    for ...loop:
        code1
        code2
        code3
        If condition:
             code
        Else:
             If condition:
                 code
                 exit_flag= False
                 break
    If exit_flag == True:
        break



0
投票

你可以定义一个类来管理迭代(报告),并允许你在循环中强制执行一定数量的重复。

class Repeatable:
    def __init__(self,iterable):
        self.iterable   = iterable

    def __iter__(self):
        for result in self.iterable:
            self.repeat = None
            yield result
            while self.repeat:
                yield result
                self.repeat -= 1

用法:

newReports = Repeatable(reports)  # <-- encapsulate the iterator
for report in newReports:         # <-- iterate over the encapsulation
    check_if_table_exists_in_SQL_DATABASE_for_report_name
    download_report_using_request_in_csv
    preprocess_file_to_change_it
    get_Column_names_from_csv_file
    if check_if_table_exists_in_SQL_DATABASE_for_report_name = False:# table doesnt exist in DB
        create table
    else
        if cols_in_sql_table != cols_in_Csv_file:
            drop_Current_table
            newReports.repeat = 1 # <-- force one more iteration with current value
© www.soinside.com 2019 - 2024. All rights reserved.