Object References
What is actually happening when you make a variable assignment? This is an important question in Python, because the answer differs somewhat from what you’d find in many other programming languages. Python is a highly object-oriented language. In fact, virtually every item of data in a Python program is an object of a specific type or class.
00:00 Welcome to this second video, where we’re going to take a deep dive into object references and we’re going to understand what’s going on.
00:08 These are the three topics that we’re going to talk about mostly. The most important one is that everything’s an object in Python. Then we’re going to talk about that variables are references, and we’re going to look at a couple of examples with some nice graphics as well.
00:21 Then we’re just going to mention what is an orphaned object and what happens in Python with orphaned objects. Let’s get going. So, the first and most important thing that I mentioned before is that everything in Python is an object. You should just keep that in mind, that’s why it’s in this big yellow box.
00:37 Keep remembering that everything in Python is an object. That means a string—when you create a string, you’re creating an object. When you create an integer, it’s an object in Python.
00:46 When you make your own objects, of course, that’s also going to be an object. And even things, like, that you might not expect—like, a function is also an object in Python.
00:56
So just, everything’s an object, ha. Keep that in mind, and you’ll see why it’s important in just a second. So, what happens when we do this standard variable assignment that we talked about before? We’re saying n = 300
.
01:08
Let’s head over to the IPython shell and just give it a try, put it in here, n = 300
. Now I can reference 300
with the variable name n
. What actually happens is that I create a reference to an object.
01:25
I’m creating a Python object with the value 300
and then I’m pointing the variable name n
to that object. That’s what’s going on here. What happens now if I say m = n
? All right, so I say m = n
. And now I can access 300
also with m
, and I’m accessing the same object.
01:48
So what I’m creating here is I’m creating another pointer to the same object, so I’m saying n
points to the object with the value of 300
, and now m
also points to that same object. That’s what’s happening when I say m = n
.
02:05
What happens now, after doing these two steps, when I say m = 400
?
02:12
So here, currently m
points to 300
, right? But now I say m = 400
—there we are. And now when I type in m
, I get as a response 400
.
02:24
So it’s not pointing anymore to 300
, but it created a new object with a value 400
, another integer object, and now m
is pointing to that value.
02:34
You can think of it like this. n
is still pointing to 300
, to that object here, but m
is pointing now to a different object with the value 400
.
02:44
Now, what happens when we do this, as a next step? We’re going to assign n
to "foo"
.
02:52
Over here, I’ll say n = "foo"
,
02:56
and now as we would expect, I can access the value of "foo"
. This is now a string, it’s not an integer anymore. And I can access it by typing m
. m
still points to 400
.
03:08
So, what happened to 300
?
03:12
What we did is I moved the reference of n
to a different object, just as I did before with m
. At first, m
was pointing to 300
and n
was pointing to 300
, and now both of them are pointing to different objects.
03:27
What happened to 300
is that it became an orphaned object. That means that we don’t have any way of accessing it anymore in our program. All the references to it have been changed, so it just sits there.
03:41
And what Python does in that case is called garbage collection. So, at some point in the life cycle of the program, Python notices that there is this object, 300
, that there’s no way of it being accessed anymore, so it just comes around and collects it and just removes it out of memory.
03:58 And that’s the end of the lifecycle of this specific object.
04:03 So, as a quick recap about object references, the important thing to remember is that everything is an object. Be it an integer or whatever, anything that we create in Python is actually an object.
04:15
And then we talked about variable references. So, you can think of, if you do something like n = 300
, think of it as you’re creating a name for a reference that points to a specific object. And then we quickly talked about orphaned objects, that if you remove all the references to an object, there’s nothing pointing to it anymore. It becomes an orphaned object, and Python automatically at some point comes with its cleanup truck and does the garbage collection on those objects.
04:44 And that’s all for object references. Let’s move on to the next topic in the next video. See you there!
Martin Breuss RP Team on March 1, 2020
Glad you liked it @emalfiza! :D
Greish on Dec. 3, 2020
This lesson was very educational. I now understand better what happens in the background :D
Superstars111 on Feb. 21, 2021
I’ve a question. Let’s say you reassign n
and m
to other objects, as in the video, but then later on you assign one or both of them back to 300. Is this sending them back to the original 300 object, or is it generating a new object which also has the value of 300? And, if the latter, is there any difference in how it works?
Bartosz Zaczyński RP Team on Feb. 22, 2021
@Superstars111 That’s a great question! It touches upon a little more advanced concept, but in short, the answer will depend on the object’s type and value.
Integers in Python are immutable, so every time you assign a numeric literal to a variable, you’re creating a new copy that’ll have a unique memory address:
>>> n = 300; id(n)
140606358419440
>>> n = 300; id(n)
140606358419472
>>> n = 300; id(n)
140606358418704
The built-in id()
function will tell you the memory address of an object the variable is pointing to. Notice how each line shows a different address.
However, that’s not true for a small subset of integers due to an optimization mechanism available in CPython. Take a look at this:
>>> n = 256; id(n)
140606474090896
>>> n = 256; id(n)
140606474090896
>>> n = 256; id(n)
140606474090896
Instances of numbers between -5 and 256 are stored in a global cache, so typing their literals will always get you the same objects.
But it’s not the end of the story. There’s yet another optimization mechanism in place. If you type the same integer literal multiple times on a single line, then it won’t matter how big that value is:
>>> print(id(300), id(300), sep="\n")
140606359853296
140606359853296
Python will always cache them anyway.
damircicic on June 28, 2023
Great tutorial. But,it seems to me false to say that everything is an object in Python. Variables don’t seem to be objects!
Bartosz Zaczyński RP Team on June 29, 2023
@damircicic Variables in Python are simply labels attached to objects stored in memory. In this context, “everything” means all data that Python represents internally. Therefore, even though you don’t explicitly see them as objects, they’re indeed stored as such in memory.
Become a Member to join the conversation.
emalfiza on Feb. 27, 2020
Wow! wow Martin you nailed it…smooth and the best description and illustration of variables for me! thank you