A Python félelmetes nyelv. Az egyszerűsége miatt sokan választják első programozási nyelvként.
Tapasztalt programozók a Python-t is folyamatosan használják, köszönhetően a széles közösségnek, a rengeteg csomagnak és az egyértelmű szintaxisnak.
De van egy kérdés, amely úgy tűnik, hogy megzavarja a kezdőket és néhány tapasztalt fejlesztőt: a Python objektumok. Pontosabban, a különbség a változtatható és a megváltoztathatatlan objektumok között.
Ebben a bejegyzésben elmélyítjük ismereteinket a Python-objektumokról, megtanuljuk a különbséget a mutálható és a megváltoztathatatlan objektumok között, és meglátjuk, hogyan használhatjuk az értelmezőt a Python működésének jobb megértéséhez.
Fontos funkciókat és kulcsszavakat fogunk használni, például: id
és is
, és megértjük a x == y
és közötti különbséget x is y
.
Felkészültél rá? Kezdjük el.
A Pythonban minden objektum
Más programozási nyelvektől eltérően, ahol a nyelv objektumokat támogat , a Pythonban valóban minden objektum - egész számokkal, listákkal és még függvényekkel is.
Tolmácsunk segítségével ellenőrizhetjük, hogy:
>>> isinstance(1, object) True >>> isinstance(False, object) True def my_func(): return "hello" >>> isinstance(my_func, object) True
A Python rendelkezik beépített funkcióval, id
amely visszaadja a memóriában lévő objektum címét. Például:
>>> x = 1 >>> id(x) 1470416816
Fent létrehoztunk egy objektumot a neve alapján x
, és hozzá rendeltük az értékét 1
. Ezután felhasználtuk id(x)
és felfedeztük, hogy ez az objektum 1470416816
a memóriában található címen található.
Ez lehetővé teszi számunkra, hogy érdekes dolgokat ellenőrizzünk a Pythonról. Tegyük fel, hogy a Pythonban két változót hozunk létre - egyet a x
és a másik nevével y
-, és azonos értéket rendelünk hozzájuk. Például itt:
>>> x = "I love Python!" >>> y = "I love Python!"
Az egyenlőség operátor ( ==
) segítségével ellenőrizhetjük, hogy valóban ugyanaz az értékük van-e a Python szemében:
>>> x == y True
De ezek ugyanazok a tárgyak a memóriában? Elméletileg itt két nagyon különböző forgatókönyv lehet.
Az (1) szcenárió szerint valóban két különböző objektumunk van, az egyik a neve, a x
másik pedig a neve y
, amelyek véletlenül ugyanazzal az értékkel bírnak.
Mégis előfordulhat, hogy a Python itt csak egy objektumot tárol, amelynek két neve hivatkozik - ahogy a (2) forgatókönyv mutatja :

A id
fent bemutatott funkcióval ellenőrizhetjük ezt:
>>> x = "I love Python!" >>> y = "I love Python!" >>> x == y True >>> id(x) 52889984 >>> id(y) 52889384
Tehát, mint láthatjuk, a Python viselkedése megegyezik a fent leírt (1) forgatókönyvvel. Annak ellenére, hogy x == y
ebben a példában (vagyis x
és y
azonos értékeket ), ezek különböző objektumok memóriában. Ennek oka id(x) != id(y)
, amint azt kifejezetten ellenőrizhetjük:
>>> id(x) == id(y) False
Van egy rövidebb módszer a fenti összehasonlításra, vagyis a Python is
operátorát kell használni . Annak ellenőrzése, hogy x is y
ugyanaz, mint ellenőrzés id(x) == id(y)
, amely eszköz-e x
, és y
az ugyanazt a tárgyat a memóriában:
>>> x == y True >>> id(x) == id(y) False >>> x is y False
Ez rávilágít az egyenlőség operátor ==
és az identitás operátor közötti fontos különbségre is
.
Amint a fenti példában láthatja, teljesen lehetséges, hogy a Pythonban ( x
és y
) két név két különböző objektumhoz van kötve (és így x is y
van False
), ahol ennek a két objektumnak ugyanaz az értéke (így x == y
van True
).
Hogyan hozhatunk létre egy másik változót, amely ugyanarra az objektumra x
mutat, amelyre mutat? Egyszerűen használhatjuk a hozzárendelés operátort =
, például:
>>> x = "I love Python!" >>> z = x
Az is
operátor használatával ellenőrizhetjük, hogy valóban ugyanarra az objektumra mutatnak-e .
>>> x is z True
Természetesen ez azt jelenti, hogy a memóriájukban megegyezik a címük, mivel ezt kifejezetten ellenőrizhetjük a következők használatával id
:
>>> id(x) 54221824 >>> id(z) 54221824
És természetesen ugyanaz az értékük, ezért várhatóan x == z
visszatérünk True
is:
>>> x == z True
Változtatható és megváltoztathatatlan objektumok a Pythonban
Azt mondtuk, hogy a Pythonban minden objektum, mégis fontos különbség van az objektumok között. Egyes objektumok változtathatóak, míg mások változhatatlanok .
Mint már korábban említettem, ez a tény sok ember számára zavart okoz, akik újak a Pythonban, ezért meg fogunk győződni arról, hogy világos.
Változhatatlan objektumok a Pythonban
Néhány Python-típus esetében, miután létrehoztunk ilyen típusú példányokat, azok soha nem változnak. Ezek megváltoztathatatlan .
Például az int
objektumok megváltoztathatatlanok a Pythonban. Mi fog történni, ha megpróbáljuk megváltoztatni egy int
objektum értékét ?
>>> x = 24601 >>> x 24601 >>> x = 24602 >>> x 24602
Nos, úgy tűnik, hogy x
sikeresen változtunk . Pontosan itt keveredik össze sok ember. Mi történt pontosan itt a motorháztető alatt? Használjuk id
a következő vizsgálatra:
>>> x = 24601 >>> x 24601 >>> id(x) 1470416816 >>> x = 24602 >>> x 24602 >>> id(x) 1470416832
Tehát láthatjuk, hogy a hozzárendeléssel x = 24602
nem változtattuk meg a x
korábban kötött objektum értékét . Inkább létrehoztunk egy új objektumot, és ahhoz kötöttük a nevet x
.
Tehát hozzárendelését követően 24601
a x
használatával x = 24601
, mi volt a következő állam:

A használat után x = 24602
létrehoztunk egy új objektumot, és a nevet x
ehhez az új objektumhoz kötöttük . A másik objektum értékével 24601
már nem érhető el x
(vagy ebben az esetben más névvel):

Whenever we assign a new value to a name (in the above example - x
) that is bound to an int
object, we actually change the binding of that name to another object.
The same applies for tuple
s, strings (str
objects), and bool
s as well. In other words, int
(and other number types such as float
), tuple
, bool
, and str
objects are immutable.
Let's test this hypothesis. What happens if we create a tuple
object, and then give it a different value?
>>> my_tuple = (1, 2, 3) >>> id(my_tuple) 54263304 >>> my_tuple = (3, 4, 5) >>> id(my_tuple) 56898184
Just like an int
object, we can see that our assignment actually changed the object that the name my_tuple
is bound to.
What happens if we try to change one of the tuple
's elements?
>>> my_tuple[0] = 'a new value' Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment
As we can see, Python doesn't allow us to modify my_tuple
's contents, as it is immutable.
Mutable objects in Python
Some types in Python can be modified after creation, and they are called mutable. For example, we know that we can modify the contents of a list
object:
>>> my_list = [1, 2, 3] >>> my_list[0] = 'a new value' >>> my_list ['a new value', 2, 3]
Does that mean we actually created a new object when assigning a new value to the first element of my_list
? Again, we can use id
to check:
>>> my_list = [1, 2, 3] >>> id(my_list) 55834760 >>> my_list [1, 2, 3] >>> my_list[0] = 'a new value' >>> id(my_list) 55834760 >>> my_list ['a new value', 2, 3]
So our first assignment my_list = [1, 2, 3]
created an object in the address 55834760
, with the values of 1
, 2
, and 3
:

We then modified the first element of this list
object using my_list[0] = 'a new value'
, that is - without creating a new list
object:

Now, let us create two names – x
and y
, both bound to the same list
object. We can verify that either by using is
, or by explicitly checking their id
s:
>>> x = y = [1, 2] >>> x is y True >>> id(x) 18349096 >>> id(y) 18349096 >>> id(x) == id(y) True
What happens now if we use x.append(3)
? That is, if we add a new element (3
) to the object by the name of x
?
Will x
by changed? Will y
?
Well, as we already know, they are basically two names of the same object:

Since this object is changed, when we check its names we can see the new value:
>>> x.append(3) >>> x [1, 2, 3] >>> y [1, 2, 3]
Note that x
and y
have the same id
as before – as they are still bound to the same list
object:
>>> id(x) 18349096 >>> id(y) 18349096

In addition to list
s, other Python types that are mutable include set
s and dict
s.
Implications for dictionary keys in Python
Dictionaries (dict
objects) are commonly used in Python. As a quick reminder, we define them like so:
my_dict = {"name": "Omer", "number_of_pets": 1}
We can then access a specific element by its key name:
>>> my_dict["name"] 'Omer'
Dictionaries are mutable, so we can change their content after creation. At any given moment, a key in the dictionary can point to one element only:
>>> my_dict["name"] = "John" >>> my_dict["name"] 'John'
It is interesting to note that a dictionary's keys must be immutable:
>>> my_dict = {[1,2]: "Hello"} Traceback (most recent call last): File "", line 1, in TypeError: unhashable type: 'list'
Why is that so?
Let's consider the following hypothetical scenario (note: the snippet below can't really be run in Python):
>>> x = [1, 2] >>> y = [1, 2, 3] >>> my_dict = {x: 'a', y: 'b'}
So far, things don't seem that bad. We'd assume that if we access my_dict
with the key of [1, 2]
, we will get the corresponding value of 'a'
, and if we access the key [1, 2, 3]
, we will get the value 'b'
.
Now, what would happen if we attempted to use:
>>> x.append(3)
In this case, x
would have the value of [1, 2, 3]
, and y
would also have the value of [1, 2, 3]
. What should we get when we ask for my_dict[[1, 2, 3]]
? Will it be 'a'
or 'b'
? To avoid such cases, Python simply doesn't allow dictionary keys to be mutable.
Taking things a bit further
Let's try to apply our knowledge to a case that is a bit more interesting.
Below, we define a list
(a mutable object) and a tuple
(an immutable object). The list
includes a tuple
, and the tuple
includes a list
:
>>> my_list = [(1, 1), 2, 3] >>> my_tuple = ([1, 1], 2, 3) >>> type(my_list) >>> type(my_list[0]) >>> type(my_tuple) >>> type(my_tuple[0])
So far so good. Now, try to think for yourself – what will happen when we try to execute each of the following statements?
(1) >>> my_list[0][0] = 'Changed!'
(2) >>> my_tuple[0][0] = 'Changed!'
In statement (1), what we are trying to do is change my_list
's first element, that is, a tuple
. Since a tuple
is immutable, this attempt is destined to fail:
>>> my_list[0][0] = 'Changed!' Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment
Note that what we were trying to do is not change the list, but rather – change the contents of its first element.
Let's consider statement (2). In this case, we are accessing my_tuple
's first element, which happens to be a list
, and modify it. Let's further investigate this case and look at the addresses of these elements:
>>> my_tuple = ([1, 1], 2, 3) >>> id(my_tuple) 20551816 >>> type(my_tuple[0]) >>> id(my_tuple[0]) 20446248

When we change my_tuple[0][0]
, we do not really change my_tuple
at all! Indeed, after the change, my_tuple
's first element will still be the object whose address in memory is 20446248
. We do, however, change the value of that object:
>>> my_tuple[0][0] = 'Changed!' >>> id(my_tuple) 20551816 >>> id(my_tuple[0]) 20446248 >>> my_tuple (['Changed!', 1], 2, 3)

Since we only modified the value of my_tuple[0]
, which is a mutable list
object, this operation was indeed allowed by Python.
Recap
In this post we learned about Python objects. We said that in Python everything is an object, and got to use id
and is
to deepen our understanding of what's happening under the hood when using Python to create and modify objects.
We also learned the difference between mutable objects, that can be modified after creation, and immutable objects, which cannot.
We saw that when we ask Python to modify an immutable object that is bound to a certain name, we actually create a new object and bind that name to it.
We then learned why dictionary keys have to be immutable in Python.
Understanding how Python "sees" objects is a key to becoming a better Python programmer. I hope this post has helped you on your journey to mastering Python.
Omer Rosenbaum, Swimm’s Chief Technology Officer. Cyber training expert and Founder of Checkpoint Security Academy. Author of Computer Networks (in Hebrew). Visit My YouTube Channel.