Python Memory Management and Tips Transcripts
Chapter: Efficient data structures
Lecture: Data with cycles
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
Alright, let's write some code and create some cycles. Now we sort of saw that in the GC section before, but I want to start from scratch
0:08
so we have some nice, clean examples to work with, and I'm gonna create another person class here that's similar,
0:13
but not the same as what we had before. I'm just gonna paste this because we kind of did do this before. Over here, we've got our person class.
0:22
It's created, it has a name. It also auto generates its id, and it has a list of friends. It has this class method that will just auto-increment the
0:32
id, like 1, 2, 3 and so on, and then finally, this class will tell you if it was cleaned up. This will
0:38
tell you that, yes, the cycle has been broken and the thing got cleaned up, or, you know what? It didn't. So, this is off to a good start.
0:46
The other thing that I'm gonna create is something to play with it.
0:49
I'll just call it "app_cycles" following my pattern that we're going to run things that are
0:53
named "app" and just trigger so I can hit the hockey to make it run and do our fmain live template and boom, we've got something to start from.
1:01
So what I wanna do is creates two people, have a person, and the name will be Michael and a second person whose name is Sarah.
1:13
Okay, we got are two people here. Now I want to let you play with it in different ways. Sometimes they'll have cycles, sometimes they won't.
1:21
So I'm gonna ask a question. I'll say if we'll ask the user "do you want cycles?" We'll do like a "[y/n]?" We'll say "If that is equal to yes,
1:36
then we're going to create some friends" You know, we'll do that friend thing. So p1, that's Michael, append p2, and then we'll do the reverse like so.
1:46
So if they say yes, that's going to create a cycle. And then we're going to zero them out here, like that and we'll print out "program closing,
2:00
kthxbye". PyCharm thinks it's misspelled, but no, no, K, thanks, bye. That's a good thing. And let's just flush it so we can
2:10
see stuff right away. Well, let's go ahead and run this and we'll see if we have the cycle, this we've
2:16
kind of already looked at, but we're about to do something new here. So we're going to see that if we do create the cycle, this will not clean it up.
2:24
So the goodbye people, they're deleted will happen after this. But if we say no, then they'll be cleaned up right here,
2:30
Yeah? let's do that. Did we will create a cycle? Let's say no, and person was cleaned up. Michael and Sarah. K, thanks,
2:38
bye. But this time, if we say yes, the garbage collector does not have enough container object allocations. Remember it needs 700 and we've done 2.
2:47
So that's not enough, so it's not going to trigger any sort of GC. So the program exits and then basically as it goes out the door,
2:54
it does its final cleanup here. Okay, so this is pretty interesting, but I'd like the program itself to know if the cycle is detected. Now,
3:03
previously, we use that memutil thing that could tell us how many references were
3:07
pointing at a thing. But I want to introduce you to another idea that we can play with. We could use the other one,
3:14
but I think we'll learn something here as well. So I'm gonna create this thing called a "weak reference" and we can go and just
3:19
say "we're gonna create a weakref" by importing the library and we'll say "refer to
3:25
p1". What's gonna happen here is this is gonna retain something that maybe can point to the object. But it can only point the object if it hasn't been
3:34
cleaned up. So previously we could say, Well, "there was this thing out in memory and it created a cycle and it
3:42
didn't get cleaned up, but we only know that it used to be there". You can't say "let me access it as if it were still alive" or revive it
3:50
In a sense, this weak reference will let us do that. So we'll do the same here, and down at the bottom,
3:57
we'll do, I guess we'll say the things already closing or whatever, but then we'll say "if we want to check
4:04
is this thing still around?" The way you do that with a weak reference is You invoke it and it'll return p1 if it can,
4:11
if it's still around, otherwise it will return none. we'll say "if either these come
4:15
back with an object, we'll print..." This, we'll say, if either of them are alive,
4:37
we're gonna say "that's a cycle because nothing else points at it", and we'll let people know, otherwise,
4:41
"no cycles found". So let's run it just one more time with our cool weak reference. So, no. So they were cleaned up when we set them to none.
4:49
K, thanks, bye. No cycles found. Let's run this again. Yes. Create the cycle. Ah, cycles found, cycles found. And then those things got cleaned up.
5:01
Here we are in this situation where we have these person classes, they have friends. Most importantly,
5:07
we have these two things and they need to know about each other, right? Michael needs to know about Sarah. Sarah needs to know about Michael.
5:15
You might think, Well, that's just the way it is. Is there any other possible data structure or mechanism we could use that's not going to
5:24
create a cycle? Remember, these things are going to survive a while. If there's going many of them, they're going to get promoted into Gen 1
5:30
and then to Gen 2, and when those things get inspected, it's going to be expensive. They're gonna hang on around in memory longer than they
5:36
otherwise should. remember, Gen 1 is 10 times less likely and Gen 2 is 100 times less likely to be even inspected. So avoiding creating the cycle
5:47
in the first place may be a really good idea. Alright, So how do we do that? How do we create this? Well, the stage is set. In the next demo
5:54
we're going to go and use a slightly different data structure that will have the same accomplishment. Like you could say,
6:01
a friend of Michael is Sarah, and vice versa without creating cycles.