Python Memory Management and Tips Transcripts
Chapter: Efficient data structures
Lecture: Cycle busting with friend map
0:00 Alright, we're gonna bring some cool stuff together,
0:02 and we're going to solve this problem by using a new data structure for our friends.
0:05 Alright, so what I want to do is I want to create a
0:09 data structure whose job is to manage the relationships. So that thing will exist
0:15 and it'll hold on to say,
0:16 p1 and p2, and it will know that we should point from
0:20 p1 to 2 or 2 to 3 or 3 to 1,
0:22 or whatever the relationship is. And then when we're done using them,
0:26 we can say "we're done with this person",
0:28 and it can drop all of those references.
0:31 And actually, you'll see,
0:32 It won't even really need to do that to work correctly.
0:35 So I'm gonna call this data structure a "friend map".
0:42 Now, at the heart of this is we're gonna have a thing
0:44 I'm gonna call a "map", but notice that's a function.
0:47 So we can call it "mp" or whatever,
0:51 but I also want it to not actually be directly manipulatable from the outside.
0:55 And so we can do that in Python by putting a double underscore and then it'll
0:59 effectively be hidden. So this,
1:01 I'm gonna have some help here,
1:03 so this is gonna be a dictionary of, given an integer,
1:06 this is the user id,
1:07 it's gonna return a list, which is one of these, and same for dictionary.
1:13 So given a person id, like 1, 7 or 500 or whatever,
1:18 return me a list of their friends. And
1:24 a dictionary would be fine,
1:26 but I would like to also have the case when you ask for somebody who we've
1:29 not entered or dealt with yet,
1:31 to just say "no, no friends for that person".
1:33 So we'll just say "defaultdict" rather than a regular dictionary.
1:38 And it's going to be calling the list function when it finds a missing item.
1:43 So, for example, nothing's added yet,
1:45 right? If I asked for a map of 5, 6 or whatever it is, that's going to return
1:49 an empty list and I could even append to that without crashing, without a key error
1:54 or any of that kind of stuff.
1:55 So default dicts are cool. This is hidden,
1:58 so we're gonna write a few functions to deal with this.
2:00 First of all, let's add a friend relationship here,
2:04 so I'll say "def add_friend, and we'll have a person,
2:12 a person like this. We'll go ahead and import them over there. We'll have a friend,
2:18 which is also a person". Super.
2:21 So we're gonna say "here's the person, here's their friend, set up their relationship
2:25 so, you know, whoever that is,
2:27 is the friend of this person". Pretty straightforward.
2:29 But we want to do a little error checking,
2:30 so if "not person or not friend"
2:33 so you can't be a friend of none.
2:36 You also,
2:39 unless your little bit funky, you know,
2:40 or maybe you always should be.
2:43 Whatever, I don't know if you should be a friend of yourself.
2:50 Right, you certainly don't need this thing to know whether you should be a friend
2:53 of yourself. And then finally,
2:55 we're gonna have a function down here
2:56 "def is_friend", the exact same thing here that returns a bool.
3:07 Alright, now return False.
3:10 You've already set this relationship up, we don't need to do it as well.
3:13 So "if is_friend (person, friend)" return.
3:20 We don't need to enter them into this data structure twice.
3:23 Alright, Now, here's where it gets interesting.
3:25 So what we're gonna do is we're gonna say your current friends,
3:28 the friends of person, not this one,
3:30 but let's call it existing friends,
3:33 existing friends or current friends, current.
3:36 Current friends. So this relationship is stored over in the map, we'll go to the map
3:43 and we'll get the friend id, so a person.id and remember
3:48 if they've never set this up before,
3:50 this is going to create an empty list for person.id and then
3:55 we're gonna add them, or if it's already there,
3:57 it's just going to return another list.
4:00 Now, here's where it gets interesting.
4:02 Do we just do this "append
4:05 friend"? Well, if we do,
4:07 we're kind of back in the same situation. Now,
4:09 this thing, right, if we somehow forget to clean up the memory here,
4:13 well, this thing is gonna hold our reference to friend,
4:15 and it will never get cleaned up.
4:17 That would be a bummer, right?
4:19 So we're gonna do something a little bit different.
4:22 We're going to go and add a weak reference.
4:25 Remember, we just spoke about that,
4:27 but we can use that here like this so we'll have the ability to get all
4:32 the friends back for the friends who have not been cleaned up or deleted or vanished
4:36 and the ones who have will be able to test
4:39 "Oh, that person's already gone.
4:41 They don't exist in the system anymore,
4:42 so they're not really friends" alright?
4:45 So what we can do is we can actually store this weak reference.
4:47 But if you ask for the friends of somebody,
4:50 yeah, you'll be able to just give it back.
4:53 How cool is that? Okay,
4:54 so this is going to let us add a friend and let's go and start by
4:57 Fixing this here. We'll say "friend_map" and import that at the top.
5:03 And we'll say, "add_friend",
5:05 so p1 and p2 two and vice versa,
5:09 like that. Now, down here,
5:12 we have to change this. Instead
5:15 of the p1 that's in here,
5:16 we'll say "friend_map.is_friend"
5:21 we're referencing p2 and the friend would be p1.
5:26 So just like that. Now remember this one always returns false.
5:29 We haven't finished this one. Yeah,
5:32 p3. It goes like that. So, let's go ahead and run it and see what happens.
5:35 Yes. Create some cycles. Are they friends? No.
5:38 Because we said, just No.
5:39 But notice there's no cycles found,
5:43 okay? Well, that doesn't really prove anything yet.
5:45 We haven't been able to accomplish the same relationships we wanted before,
5:50 right? So, we're part way there. We're able to add these friends theoretically,
5:56 and we haven't been able to test them,
5:59 but we're getting there. So we're gonna have to write "is_friend",
6:04 and it turns out that this function is not too bad.