Python chalkashishi - konventsiya, nom va qiymat

Men pythonni o'rganayotganimda boshlang'ichman va chalkashlik bor. Quyidagi python kodi mavjud bo'lsa:

import numpy as np
X = np.array([1,0,0])
Y = X
X[0] = 2
print Y

Y will be shown to be array([2, 0, 0])

Ammo, agar quyidagilarni qilsam:

import numpy as np
X = np.array([1,0,0])
Y = X
X = 2*X
print Y

Y is still array([1,0,0])

Nima bo'lyapti o'zi?

5
Y , mahalliy o'zgaruvchini X deb o'zgartirsangiz, Y kodi> X mavjud.
qo'shib qo'ydi muallif Willem Van Onsem, manba
yangi ma'lumotlar strukturasini ishlab chiqaruvchi * operatoridan foydalangan holda, ma'lumot strukturasini mutatsiya qiladi. Shuningdek, buni o'qing va tushunib oling: nedbatchelder.com/text/names.html
qo'shib qo'ydi muallif juanpa.arrivillaga, manba
yangi ma'lumotlar strukturasini ishlab chiqaruvchi * operatoridan foydalangan holda, ma'lumot strukturasini mutatsiya qiladi. Shuningdek, buni o'qing va tushunib oling: nedbatchelder.com/text/names.html
qo'shib qo'ydi muallif juanpa.arrivillaga, manba
Thanks @ juanpa.arrivillaga Hujjat juda foydali
qo'shib qo'ydi muallif SunnyIsaLearner, manba
Thanks @ juanpa.arrivillaga Hujjat juda foydali
qo'shib qo'ydi muallif SunnyIsaLearner, manba
Thanks @ juanpa.arrivillaga Hujjat juda foydali
qo'shib qo'ydi muallif SunnyIsaLearner, manba
Tashakkur, afsuski men postda aniq emasdim. Yuqoridagi asl nusxada X [0] = 2 ni X = 2 * X ga o'zgartiraman.
qo'shib qo'ydi muallif SunnyIsaLearner, manba
Tashakkur, afsuski men postda aniq emasdim. Yuqoridagi asl nusxada X [0] = 2 ni X = 2 * X ga o'zgartiraman.
qo'shib qo'ydi muallif SunnyIsaLearner, manba

7 javoblar

bu haqda o'ylab ko'ring: Pythonda tenglashtirilgan belgilar havolalar keltiradi.

Y = X makes Y point to the same address X points to

X[0] = 2 makes x[0] point to 2

X = 2*X makes X point to a new thing, but Y is still pointing to the address of the original X, so Y is unchanged

Bu aniq emas, lekin uning tamoyilini tushunish uchun etarlicha yaqin

8
qo'shib qo'ydi
np.ndarray moslamalari ishlayotganini hisobga olib, "X [0] = 2 x [0] nuqtasiga 2" ni keltirib chiqaradi, ammo bu oxirgi rad javobidan pastga tushmaydi.
qo'shib qo'ydi muallif Mad Physicist, manba

bu haqda o'ylab ko'ring: Pythonda tenglashtirilgan belgilar havolalar keltiradi.

Y = X makes Y point to the same address X points to

X[0] = 2 makes x[0] point to 2

X = 2*X makes X point to a new thing, but Y is still pointing to the address of the original X, so Y is unchanged

Bu aniq emas, lekin uning tamoyilini tushunish uchun etarlicha yaqin

8
qo'shib qo'ydi
np.ndarray moslamalari ishlayotganini hisobga olib, "X [0] = 2 x [0] nuqtasiga 2" ni keltirib chiqaradi, ammo bu oxirgi rad javobidan pastga tushmaydi.
qo'shib qo'ydi muallif Mad Physicist, manba

bu haqda o'ylab ko'ring: Pythonda tenglashtirilgan belgilar havolalar keltiradi.

Y = X makes Y point to the same address X points to

X[0] = 2 makes x[0] point to 2

X = 2*X makes X point to a new thing, but Y is still pointing to the address of the original X, so Y is unchanged

Bu aniq emas, lekin uning tamoyilini tushunish uchun etarlicha yaqin

8
qo'shib qo'ydi
np.ndarray moslamalari ishlayotganini hisobga olib, "X [0] = 2 x [0] nuqtasiga 2" ni keltirib chiqaradi, ammo bu oxirgi rad javobidan pastga tushmaydi.
qo'shib qo'ydi muallif Mad Physicist, manba

Buning sababi X va Y bir xil ob'ektga np.array ([1,0,0]) > X yoki Y orqali amalga oshirilganligini hisobga olmaganda, natijalar bir xil bo'ladi, lekin em> birining namunasi, hech qanday ta'siri yo'q.

Agar yozsangiz:

X = np.array([1,0,0])
Y = X

asosan, bir xil ob'ektga qarash ikkita mahalliy o'zgaruvchilar X va Y mavjud. Shunday qilib, xotira ko'rinadi:

     +--------+
Y -> |np.array| <- X
     +--------+
     |[1,0,0] |
     +--------+

Endi agar siz X [0] = 2 ni ishlatsangiz, u asosan quyidagicha:

X.__setitem__(0,2)

shuning uchun ob'ektdagi usulni chaqiradi . Shunday qilib, xotira shunga o'xshash:

     +--------+
Y -> |np.array| <- X
     +--------+
     |[2,0,0] |
     +--------+

Agar siz yozsangiz:

X = 2*X

birinchi 2 * X baholandi . Keling, 2 * X quyidagi uchun qisqa:

X.__rmul__(2)

( X uchun __ mul __ ni qo'llab-quvvatlasa 2 = Python birinchi ko'rinadi, lekin 2 /code>), Python kodi X.__ rmul __ ga qaytadi). Endi X .__ rmul __ X kodini o'zgartirmaydi: X buzilmaydi qoldiradi, lekin yangi qatorni va qaytaradi. X , bu qatorga murojaat qiladigan yangi qator tomonidan ushlanadi).

array ([4, 0, 0]) va keyin X yangi array /strong>. Shunday qilib, xotira shunga o'xshash:

     +--------+         +--------+
Y -> |np.array|     X ->|np.array|
     +--------+         +--------+
     |[2,0,0] |         |[4,0,0] |
     +--------+         +--------+

Lekin siz ko'rib turganingizdek, Y hali ham eski obyektga havolalar .

5
qo'shib qo'ydi
Yo'q, bu __ rmul __ :) deb ataydi.
qo'shib qo'ydi muallif Willem Van Onsem, manba
@MadPhysicist: buni aniqlash uchun rahmat.
qo'shib qo'ydi muallif Willem Van Onsem, manba
Yaxshi fikr. Men ham menikini yangilayman.
qo'shib qo'ydi muallif Mad Physicist, manba
__ setitem __ ning ba'zi bir ostki chiziqlari yo'q
qo'shib qo'ydi muallif Mad Physicist, manba
Bundan tashqari, __ mul __ kabi bir usul, __ setitem __ kabi, shuning uchun ko'paytirishning Y ga tarqalmasligini tushuntirib bermaysiz.
qo'shib qo'ydi muallif Mad Physicist, manba

Buning sababi X va Y bir xil ob'ektga np.array ([1,0,0]) > X yoki Y orqali amalga oshirilganligini hisobga olmaganda, natijalar bir xil bo'ladi, lekin em> birining namunasi, hech qanday ta'siri yo'q.

Agar yozsangiz:

X = np.array([1,0,0])
Y = X

asosan, bir xil ob'ektga qarash ikkita mahalliy o'zgaruvchilar X va Y mavjud. Shunday qilib, xotira ko'rinadi:

     +--------+
Y -> |np.array| <- X
     +--------+
     |[1,0,0] |
     +--------+

Endi agar siz X [0] = 2 ni ishlatsangiz, u asosan quyidagicha:

X.__setitem__(0,2)

shuning uchun ob'ektdagi usulni chaqiradi . Shunday qilib, xotira shunga o'xshash:

     +--------+
Y -> |np.array| <- X
     +--------+
     |[2,0,0] |
     +--------+

Agar siz yozsangiz:

X = 2*X

birinchi 2 * X baholandi . Keling, 2 * X quyidagi uchun qisqa:

X.__rmul__(2)

( X uchun __ mul __ ni qo'llab-quvvatlasa 2 = Python birinchi ko'rinadi, lekin 2 /code>), Python kodi X.__ rmul __ ga qaytadi). Endi X .__ rmul __ X kodini o'zgartirmaydi: X buzilmaydi qoldiradi, lekin yangi qatorni va qaytaradi. X , bu qatorga murojaat qiladigan yangi qator tomonidan ushlanadi).

array ([4, 0, 0]) va keyin X yangi array /strong>. Shunday qilib, xotira shunga o'xshash:

     +--------+         +--------+
Y -> |np.array|     X ->|np.array|
     +--------+         +--------+
     |[2,0,0] |         |[4,0,0] |
     +--------+         +--------+

Lekin siz ko'rib turganingizdek, Y hali ham eski obyektga havolalar .

5
qo'shib qo'ydi
Yo'q, bu __ rmul __ :) deb ataydi.
qo'shib qo'ydi muallif Willem Van Onsem, manba
@MadPhysicist: buni aniqlash uchun rahmat.
qo'shib qo'ydi muallif Willem Van Onsem, manba
__ setitem __ ning ba'zi bir ostki chiziqlari yo'q
qo'shib qo'ydi muallif Mad Physicist, manba
Yaxshi fikr. Men ham menikini yangilayman.
qo'shib qo'ydi muallif Mad Physicist, manba
Bundan tashqari, __ mul __ kabi bir usul, __ setitem __ kabi, shuning uchun ko'paytirishning Y ga tarqalmasligini tushuntirib bermaysiz.
qo'shib qo'ydi muallif Mad Physicist, manba

Bu mos yozuvlar va qiymatdan ko'ra konventsiya va nomlar haqida ko'proq.

Siz tayinlaganingizda:

Y = X

Keyin Y nomi X so'ziga ishora qiluvchi ob'ektga tegishlidir. Biron bir tarzda X va Y ko'rsatgichlari bir xil ob'ektga ishora qiladi:

X is Y   # True

- ismlar bir xil ob'ektga ishora qiladimi-yo'qligini tekshiradi!


Keyinchalik bu qiyin bo'ladi: siz qatorlarda operatsiyalarni bajarasiz.

X[0] = 2

Bu "elementni tayinlash" va chaqiriqlar deb ataladi

X.__setitem__(0, 2)

__ setitem __ nima qilish kerak (konventsiya), X konteynerida ba'zi bir qiymatni yangilashdir. Shunday qilib, X yana bir xil ob'ektni keyinchalik ko'rsatishi kerak.

Biroq, X * 2 "ko'paytirish" va konventsiya bu yangi ob'ektni yaratishi kerakligini bildiradi (yana konventsiya, bu xatni X .__ mul __ ustiga yozish orqali o'zgartirishi mumkin). Shunday qilsangiz

X = X * 2

X nomi endi X * 2 yaratilgan yangi ob'ektga tegishli:

X is Y   # False

Odatdagidek keng tarqalgan kutubxonalar ushbu konvensiyalarga rioya qilishadi, lekin buni butunlay o'zgartirishingiz mumkinligini ta'kidlash muhim!

3
qo'shib qo'ydi
@MadPhysicist Siz haqsiz. Biroq, konventsiyalarni mumkin bo'lgan dasturlarni muhokama qilishdan ko'ra tushuntirish osonroqdir. Ushbu operatsiyalar uchun konventsiyalar Python ma'lumotlar modelida juda aniq. Biroq, ushbu konventsiyalarni (masalan, __ mul __ return self __ mul __ ) buzilishiga olib keladigan ko'plab dastur mavjud. Va, ha, men biroz chekyapman, ammo __ mul __ va __mul __ Python & NumPy bilan ishlaydiganligini tushuntirish uchun, agar subclasslar va __ array_priority __ bo'lsa.
qo'shib qo'ydi muallif MSeifert, manba
@SunnyYang Aslida, asl nusxa ham to'g'ri deb o'ylayman. Faqat Python "rozilik beruvchi kattalar" qoidalariga amal qilgan. Bu kabi savollarga umuman javob berish qiyin kechadi, chunki MadFiSistning fikricha, Python konventsiyalariga amal qilish kerak bo'lgan amaliyotga bog'liq. Biroq, ma'lum hollarda (va siz misol sifatida numpy qatordan foydalangansiz), javob berish oson, chunki NumPy (eng) python konvensiyalariga mos keladi.
qo'shib qo'ydi muallif MSeifert, manba
Men bu konventsiyaga qaraganda ko'proq amalga oshirish masalasi haqida gapiryapman. Anjuman bir narsani yoki boshqasini belgilashda bo'lsa-da, numpy dizilerinin amalga oshirilishi, oxirida operatorlarning xulq-atvorini belgilaydi. Bunday holda, albatta, konvensiya amal qiladi.
qo'shib qo'ydi muallif Mad Physicist, manba
Bundan tashqari, texnik jihatdan OP 2 * X haqida so'radi, shuning uchun __ rmul __ , lekin yana numpy uchun bu komutativdir.
qo'shib qo'ydi muallif Mad Physicist, manba
Sizning taklifingizga asoslanib, mening savolim nomini o'zgartirdim. Boshlovchi uchun ham savollar berish qiyin. Rahmat!
qo'shib qo'ydi muallif SunnyIsaLearner, manba

Siz X = np.array ([1, 0, 0]) deyayotganingizda, ba'zi bir usullari va undagi haqiqiy ma'lumotlarni va boshqa ma'lumotlarni o'z ichiga olgan ichki tamponlarga ega bo'lgan ob'ektni yaratasiz.

Y = X ni bajarish, xuddi shu ob'ektga murojaat qilish uchun Y ni o'rnatadi. Bunga Pythonda nomga bog'lanish deb ataladi. Siz X ga bog'langan bir xil ob'ektni Y ga qo'shishingiz mumkin.

X [0] = 2 ni bajarish, ob'ektni __ setitem __ usulini chaqiradi. Ob'ektni joyida o'zgartirsa. Endi X yoki Y qiymatlarini chop qilsangiz, ushbu ob'ektlarning buferlaridan chiqadigan raqamlar 2, 0, 0 hisoblanadi.

X = 2 * X bajarish X .__ rmul __ (2) ga tarjima qilinadi. Ushbu usul kodni X o'zgartirmagan. Yangi elementni yaratadi va qaytaradi, ularning har biri elementlarning X elementining ikki barobaridan iborat. Keyin yangi ob'ektni X nomi bilan bog'laysiz. Biroq, Y nomi hali ham asl majmuaga bog'liq, chunki siz uni o'zgartirish uchun biror narsa qilmadingiz. Bir tomondan X .__ rmul __ ishlatiladi, chunki 2 .__ mul __ (X) ishlamaydi. Numpy arrays, odatda, komutativ bo'lish uchun ko'paytirishni aniqlaydi, shuning uchun X .__ mul __//> va X .__ rmul __ bir xil narsaga ega bo'lishi kerak.

Y = Y o'zgarishlarini targ'ib qiluvchi X * = 2 ni ham amalga oshirishingiz mumkin. Buning sababi, * = operatori kirishni o'zgartiradigan usulini __ imul __ usuliga aylantirishi.

2
qo'shib qo'ydi
X * = 2 ni ko'rsatganingiz uchun tashakkur. Men buni yodda tutishim kerak yoki!
qo'shib qo'ydi muallif SunnyIsaLearner, manba
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