Когато изучавате Обектно ориентирано програмиране (ООП) в Python за първи път, ще видите, че екземпляр на клас също се нарича обект (можете да посетите този сайт, за да научите повече за ООП). Но нека ви кажа, че това не е единственото нещо, което Python нарича обект, защото всичко е обект!

Тук, в този блог, ще разгледам концепциите за обект в Python и свързаните с тях теми. Ще се опитам да ви дам много примери и да направя аналогии, за да направя понятията лесни за разбиране, така че седнете, отпуснете се и се насладете на шоуто.

Разбиране на id и тип вградени функции

Преди да се потопим в id и type, нека отговорим на въпроса: Какво е обект? Според документацията на Python:

Обектите са абстракцията на Python за данни. Всички данни в програма на Python са представени чрез обекти или чрез релации между обекти. Всеки обект има идентичност, тип и стойност.

Както прочетохме по-горе, всеки обект има уникален идентификатор. Този идентификатор е цяло число и е гарантирано, че е уникален през целия си живот. Можем да мислим за id като адресната памет на обекта. За да видим тази самоличност, използваме функцията id(), както е на изображението по-долу:

В изображението по-горе декларирам променлива с име name и й присвоявам стойност "Josue". След това използвах функцията id(), за да получа идентичността на обекта "Josue". Мислете за променливите като за псевдоними и те просто сочат към обекта. С други думи, ние създаваме препратка към този обект, както е показано по-долу:

Сега нека разберем функцията type(). Типът на даден обект ни позволява да определим какви операции може да извършва (например „има ли дължина?“). Използваме функцията type(), за да го видим:

По-горе декларирах две променливи: age и fruit, след което използвах type(), за да получа стойността на всеки обект. В случай на възраст, типът му е int (цяло число), а за плодовете типът му е str (низ). Когато предадем само аргумент на type(), той ни дава типа на обекта, но има и друга употреба на типа, когато му подаваме три аргумента (проверете тази статия, за да научите повече).

Python ни казва, че всеки обект има тип, id и стойност. Стойността на даден обект може да се променя и зависи от типа на този обект.

Променливи и неизменни обекти

Когато даден обект може да промени стойността си, без да променя идентичността си, той се нарича променлив, а ако обектът не може да го направи, той се нарича неизменен. По-долу има списък с променливи и неизменни обекти:

Има разлика в паметта между променливи и неизменни обекти, когато са създадени. Когато се създаде неизменен обект, той се разпределя в конкретно място в паметта (като всеки обект), но ако се създаде друг неизменен обект със същия тип и стойност, Python просто ще накара псевдонима да се отнася до същото място в паметта на първия обект, вместо да създавате нов. Това е известно в Python като „interning“ или „catching“ на неизменни обекти. Това действие се изпълнява с цел оптимизация.

Предварително разпределение за int обекти

Друг момент, който трябва да се отбележи, е случаят с цели числа. С техниката за улавяне на обекти, когато интерпретаторът на Python стартира, int обектите са предварително разпределени в диапазона от -5 до 257, общо 262 цели числа. Това се прави, за да се увеличи ефективността, защото позволява повторно използване на int обекти, вместо създаване на нови. За да направи това предварително разпределение, Python използва два макроса, наречени: NSMALLPOSINTS (257 не включително) и NSMALLNEGINTS (-5 включително).

#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
#endif
#ifdef COUNT_ALLOCS
Py_ssize_t quick_int_allocs;
Py_ssize_t quick_neg_int_allocs;
#endif

Ако искате да знаете по-подробно за тази тема, проверете „този сайт“ и също „този“.

Е, това беше гъсто; позволете ми да ви покажа няколко примера, за да изясня това, което казах:

По-горе декларирах два псевдонима, отнасящи се на пръв поглед до един и същ обект. За да проверя нашата хипотеза, използвах функцията id(), за да получа самоличността. Ето, псевдонимите name_1 и name_2 се отнасят за един и същ обект. Много по-добре? Ако случаят не е такъв, моля, проверете тази статия.

Това не е случаят с променливите обекти, защото ако създадем нов псевдоним, препращащ обект със същия тип и стойности като първия, те ще се отнасят до различни места в паметта:

Както можете да видите, очевидно и list_1, и list_2 се отнасят за един и същ обект, но ако използваме функцията id(), можем да видим, че те се отнасят за различни обекти. Има обаче един начин да накарате list_1 и list_2 да се отнасят към един и същ обект. Синтаксисът е list_1 = list_2 = [1, 2, 3, 4]. Готино, нали?😜

Нека проверим някои примери за това как работят immutable и mutable. Първо, примери за неизменни обекти.

В дадения пример се опитвам да променя името на променливата при индекс 1, като заменя буквата o, но ми дава грешка. Същото поведение с кортежи:

Сега е време да проверим примери за променливи обекти.

Изключения в неизменността

Това, което имам предвид, като пиша изключения в неизменността, е, че неизменните обекти, като например замразен набор, могат да съдържат препратка към променлив обект. Например кортежът може да съдържа списък или набор. Изображението по-долу илюстрира това, което казвам:

Както можем да забележим, списъкът в кортежа е променен. Това е така, защото списъкът е променлив обект и аз му създадох псевдоним, за да го модифицирам.

Концепциите за променливи и неизменни обекти е важно да знаете и да разберете как работят, защото ще обясня как се третират, когато се използват във функции.

Как аргументите се предават на функции

Когато работим с променливи и неизменни обекти, поведението на функциите е различно, защото ако предадем променлив обект по референция, той ще бъде променен (За да избегнем това, можем да използваме копие на списъка). Нека ви покажа един пример:

В предишното изображение list_ беше предадено чрез препраткакъм функцията change_list() , след което използвах конкатенация на място, за да добавя нов елемент към списъка. Ето защо първоначалният списък беше променен. Може би една графика може да обясни малко повече:

Тук горе това, което ви показвам, е как параметърът на функцията, наречена list_1, препраща към същия обект като list_. Поради тази причина, когато актуализирам list_1, list_ също се актуализира.

В случай на неизменни обекти е малко по-различно. Променливите не променят стойностите си при преминаване към функция. Това е така, защото предаваме само стойностите на обектите. Това е извикване преминаване по стойност. Нека проверим примера по-долу:

Можем да видим по-горе, че стойността на num_ е същата след извикване на функцията change_integer().

Е, надявам се шоуто да ви е харесало. По-долу ще споделя с вас някои блогове, които ми помагат да пиша този блог: K.Wong и megha mohan:





До следващия път!