Python g'ayrioddiy xatti-harakatlari bilan numaralandırın

Men bilaman, ro'yxatni loop ichida o'zgartirish kerak emas, faqat qiziqishdan tashqari, quyidagi ikkita misol orasida yinelemelerin soni nima uchun farqli ekanini bilishni istayman.

1-misol:

x = [1, 2, 3, 4, 5]
for i, s in enumerate(x):
    del x[0]
    print(i, s, x)

2-misol:

x = [1,2,3,4,5]
for i, s in enumerate(x):
    x = [1]
    print(i, s, x)

Misol 1 faqat 3 marta ishlaydi, chunki i == 3 , len (x) == 2 ).

2-misol, len (x) == 1 bo'lsa ham 5 marta ishlaydi.

Shuning uchun mening savolim enumerate loopning boshida (index, value) juftlarining to'liq ro'yxatini yaratadi va uni yineleme? Yoki ular loopning har bir iteratsiyasida yaratiladimi?

18
Xuddi shu narsa hisobga olinmasdan sodir bo'ladi! for döngüsü, iteratorni qayta baholashni amalga oshirmaydi, shuning uchun hatto x ichida uchun pastki qismini qayta topshirsangiz ham, eski qiymat. Shubhasiz agar siz ma'lumotlar ro'yxatini olib tashlasangiz, loop kamroq yineleme bilan yakunlanadi.
qo'shib qo'ydi muallif Bakuriu, manba
sanab chiqing, qo'shni qatorlar uchun ishlash kerak, shuning uchun oldingi juftlarni yaratish imkoni bo'lmaydi. Agar istasangiz, faqat ro'yxatini (enumerate (...)) ishlatish
qo'shib qo'ydi muallif John La Rooy, manba
Men sizning savolingizga javob berish uchun yetarli darajada bilimga ega emasman, lekin bu erda nima uchun boshqacha munosabatda bo'lishim - mening taxminimcha. Birinchidan, siz xuddi shu ro'yxatdan o'chirasiz, shuning uchun iteratsiya avvaldan to'xtaydi. Ikkinchi holda, siz uni qayta tayinlaysiz. Shuning uchun python uni different o'zgarmaydigan deb hisoblaydi va x ning original qiymati bilan davom etaveradi.
qo'shib qo'ydi muallif bouletta, manba
Bu narsa bir narsaga aylanishi kerak.
qo'shib qo'ydi muallif jpmc26, manba
@ jpmc26 Albatta, men kecha topa olmagan stackoverflow.com/a/986145/3451198 mavjud. Bu asosiy mavzuni juda yaxshi tushuntiradi, lekin loop kontekstida emas. Bu bayroq belgilanishi kerakmi? Men SOda yangi emasman va bunga ishonchim komil emas.
qo'shib qo'ydi muallif Wisperwind, manba

6 javoblar

Birinchi misolda, siz qayta-qayta ko'rib chiqadigan ro'yxatni o'zgartirasiz.

Boshqa tomondan, ikkinchi holatda siz faqat x nomi bilan yangi ob'ektni belgilashingiz mumkin. Qaytarib olinadigan ko'chirma ob'ekti o'zgarmasa ham.

http://foobarnbaz.com/2012/07/08/ saytiga tashrif buyuring. Python'da nomlar va o'zgaruvchilar haqida batafsilroq tushuntirish uchun tushunish-python-o'zgaruvchilar/.

22
qo'shib qo'ydi
Javobingiz uchun tashakkur! Men Watsining javobini tanladim, chunki __next __() chaqiruvi bilan tushunish ancha oson edi.
qo'shib qo'ydi muallif dbdq, manba
@dbdq Python o'zgaruvchilari qanday ishlashi bilan bog'liq, deb o'ylayman, ehtimol bu javob yanada ko'proq ko'tarilishga ega.
qo'shib qo'ydi muallif JeremiahBarrar, manba
@dbdq Mening javobim bilan bu erda nima sodir bo'layotgani aniq
qo'shib qo'ydi muallif JeremiahBarrar, manba

enumerate() returns an iterator, or some other object which supports iteration. The __next__() method of the iterator returned by enumerate() returns a tuple containing a count (from start which defaults to 0) and the values obtained from iterating over iterable.

__next__() returns the next item from the container. If there are no further items, raise the StopIteration exception.

Loopning boshida() indeks() tamsaytli (indeks, qiymat) juftlarini hosil qiladimi? Yoki ular loopning har bir iteratsiyasida yaratiladimi?

Shunday qilib, enumerate() bir yineleyiciyi qaytaradi va har bir iterasyonda, __ keyingi __() boshqa narsalar bor yoki yo'qligini tekshiradi. enumerate() loopning boshida to'liq ro'yxat yaratmaydi.

Qanday qilib @Wisperwind qayd etilgan bo'lsa, ikkinchi holda, siz yangi kodni x . Ob'ektga aylantirilsa, iteratsiya vaqtida o'zgarmaydi.

18
qo'shib qo'ydi
X = [0] belgilaganidan keyin ham asl x qiymatining [1, 2, ..., 5] qiymati axlat yig'ilmasligi sababli, iterator hali ham ushbu ro'yxatga ishora qilmoqda.
qo'shib qo'ydi muallif dbdq, manba

Faqat Wasi Ahmad va Wisperwind nima deganini tushuntirish. Har ikkala davlat "siz faqat x ga yangi ob'ekt tayinlaysiz". Bu "siz yangi ob'ekt ( [1] ) yaratmoqdasiz va uni x nomiga saqlayapsiz» deb talqin qilish mumkin bo'lganidek, biroz chalkash bo'lishi mumkin. "Xo'sh, nima uchun u o'zgarmaydi?" deb aytsa, nima bo'layotganini ko'rish uchun, ob'ekt idini

x = [1, 2, 3, 4, 5]
y = x  # To keep a reference to the original list
print id(x), id(y)
for i, v in enumerate(x):
    x = [1]
    print id(x), id(y)
print id(x), id(y)


# output (somewhat contrived as I don't have a python environment set up)
#    X ID            Y ID
10000000000001 10000000000001
10000000000002 10000000000001
10000000000003 10000000000001
10000000000004 10000000000001
10000000000005 10000000000001
10000000000006 10000000000001
10000000000006 10000000000001

x id kodini har doim loop orqali o'zgartiradigan va loop bilan tugallanganda x pastki qismdagi oxirgi modifikatsiyada. O'zingizning loopingizdan o'tib ketganingizda, u x ning asl nusxasi ustida yinelanadi, siz unga murojaat qila olmasligingizdan qat'i nazar.

Ko'rib turganingizdek y asl x ga ishora qiladi. O'zingizning ierarxiyalaringizni loop orqali yaratganingizda, x o'zgargan bo'lsa-da, y hali ham aslida x .

8
qo'shib qo'ydi
Ushbu kodni ishga tushirganimda loop ichidagi x id raqami 139917134004304 va 139917134053248 orasida o'zgarib turadi. Buning sababi, yangi ob'ekt oxirgi but-bitta ob'ekt bilan bir xil joyda yaratilganligi. Biroq, bu ajinlar sizning javobingizni yanada murakkablashtirishi mumkin!
qo'shib qo'ydi muallif Martin Bonner, manba
Bunga qo'shimcha ravishda, OX x havola qilingan (va u looplashtirilgan) original ro'yxatini kamaytirishni istasa, u del x [1: ]: x [0] = 1
qo'shib qo'ydi muallif Martin Bonner, manba
@MartinBonner Yoki hatto: x [:] = [1]
qo'shib qo'ydi muallif Robin, manba
Python juda mos keladigan tildir. Siz x nomiga qiymat tayinlamaysiz, x nomiga havola berasiz.
qo'shib qo'ydi muallif Penguin Brian, manba

Haqiqatdan ham: Sizning birinchi snippetingiz takrorlangan ro'yxatni o'zgartiradi; enumerate() tomonidan transversed ro'yxat o'zgartirilmagan qoldirib, yangi ro'yxatga x o'zgarmaydigan ikkinchi nuqta. Siz buni www.pythontutor.com saytidagi quyidagi havolalarga borib ko'rishingiz mumkin: bu sizning kodingizni bir martalik bajarishga va o'zingizning o'zgaruvchilari tarkibingizni tasavvur qilish imkonini beradi:

To better see what's going on, go here instead to step over the following expanded code:

x = [1,2,3,4,5]
view = enumerate(x)
for i, s in view:
    x = [1]
    print(i, s, x)
1
qo'shib qo'ydi

Ba'zilari allaqachon sizning ikkinchi misolingiz faqat x nuqtalarining qiymatini o'zgartirganligiga ishora qilmoqdalar, lekin siz ularni qayta-qayta o'zgartiradigan ro'yxat emas. Bu oddiy topshiriq ( x = [1] ) va tilni belgilash orasidagi farq uchun mukammal bir misol. ( x [:] = [1] ). Ikkinchisi joyida x belgilarini o'zgartiradi:

x = [1, 2, 3, 4, 5]
for i, s in enumerate(x):
    x[:] = [1]
    print(i, s, x)

bosib chiqaradi

(0, 1, [1])
1
qo'shib qo'ydi
x = [1, 2, 3, 4, 5]

The list [1, 2, 3, 4, 5] is 'tagged' with x

for i, s in enumerate(x):

x [1, 2, 3, 4, 5] va y tagiga kiritilgan. enumerate() y yorlig'ini emas, balki y yorlig'ini ishlatishni davom ettiradi.

del x[0]

The list stored in memory is modified, so x and y now both refer to [2, 3, 4, 5]

Shu bilan bir qatorda, foydalanganda

x = [1]

Yangi ro'yxat [1] xotirada yaratilgan va x yorlig'i hozir unga ishora qiladi. y yorlig'i hali ham asl ro'yxatga ishora qilmoqda.

How Python variable work:
http://foobarnbaz.com/2012/07/08/understanding-python-variables/

0
qo'shib qo'ydi
Python
Python
372 ishtirokchilar

Bu guruh python dasturlash tilini muhokama qilish uchun. Iltimos, o'zingizni hurmat qiling va faqat dasturlash bo'yicha yozing. Botlar mavzusini @botlarhaqida guruhida muhokama qling! FAQ: @PyFAQ Offtopic: @python_uz_offtopic

Python offtopic group !
Python offtopic group !
150 ishtirokchilar

@python_uz gruppasining offtop gruppasi. offtop bo'lsa ham reklama mumkin emas ) Boshqa dasturlash tiliga oid gruppalar @languages_programming