所以,我正在做一个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语句,但我想这是不受欢迎的......所以检查什么是最好的方式来做到这一点。
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()
你可以使用生成器 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)
听起来你想要一个额外的 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()
不管怎么说
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
因为它不允许在循环时进行修改),但我觉得单行的改变很有趣 :)
你可以使用 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)
你可以尝试把整个逻辑放在一个无限的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
你可以定义一个类来管理迭代(报告),并允许你在循环中强制执行一定数量的重复。
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