یک مشکلی که گاها ممکنه بعضی از دوستان بهش بر بخورن و در نگاه اول رفتار عجیب و غریبی ببینید از پایتون ، iterate کردن روی یه لیست (یا هر sequence type دیگه) و همزمان حذف آیتم از اون لیست هست. مثال :
lst = ['a', 'b', 'c']
for i in lst:
lst.remove(i)
print(lst)
انتظار میره همه آیتم ها remove شده باشن و لیست خالی شده باشه ولی خروجی به ما این رو میده:
output: ['b']
و اما دلیل :
وقتی روی sequence type ها شما for میزنین ، یه متغیری مثلا index فارغ از اینکه چه اتفاقی در for میفته دونه دونه اضافه میشه و به
__getitem__ اون لیست فرستاده میشه برای گرفتن آیتم جدید. به طور مثال این دو کد زیر باهم برابر هستن :
lst = [1, 2, 3, 4]
for i in lst:
print(i * 10)
print('------------------')
index = 0
while True:
try:
i = lst.__getitem__(index)
except IndexError:
break
print(i * 10)
index += 1
بریم سر مثال اصلیمون. وقتی ما یک آیتم رو از ابتدای لیست حذف میکنیم همه ی آیتم های بعدی شیفت میشن به سمت چپ چون همیشه باید ایندکس ها از صفر شروع بشن.(دلیل اینکه time complexity متد remove میشه O(n) همین هست.)
پس اگه بخوایم فقط iteration اول رو در نظر بگیریم ، الان آیتم "a" که در ایندکس صفر بوده حذف شده از لیست و آیتم "b" اومده توی ایندکس صفر ! ولی اون متغیر index مون که برای خودش توی هر iteration یکی اضافه میشد چند شده ؟ شده 1 !
پس توی iteration دوم ایندکس شماره 1 خواسته میشه از لیست که در حال حاضر "c" در این ایندکس قرار داره. این وسط "b" موند داخل لیست...
راه حل استفاده از copy :
lst = ['a', 'b', 'c']
for i in lst.copy():
lst.remove(i)
print(lst)
خروجی :
output : []