Python Memory Management and Tips Transcripts
Chapter: Python variables and memory
Lecture: Flyweight numbers in CPython
0:00 Alright, let's do one more demo.
0:01 Let's explore this idea of flyweight numbers.
0:04 So, I'm gonna create a new little thing we can run here, app, remember
0:09 that means you should run it directly,
0:14 all right. And we'll do our fmain to just boom pop us into the
0:18 right pattern. And I copied some text here that's just gonna help us a little
0:21 bit. So this is gonna be an example showing number,
0:24 which numbers are pre computed and reused.
0:27 That is the flyweight pattern. And what I want to do is come up with
0:31 a range of numbers from -1000 to
0:34 1000, and then we're just going to say for this 872 and that 872 are
0:40 they the same? So a really simple way to do that is to have just
0:43 two lists, each with -1000 to 1000 numbers in them,
0:47 like -1000, -999 etcetera.
0:50 It will say this is gonna be a list of range from -1000 to 1001.
0:57 Annoying, but it doesn't include the end right in this range thing,
1:03 and we'll do that for 2. We're going to do it twice.
1:07 What we want to see is by doing it twice,
1:10 even though the exact same values will be in there,
1:13 will they be the same memory address?
1:14 Will they literally be the same PyObject pointer thing in memory?
1:18 Or will they just be the equivalent values?
1:22 All right, and a way to do that,
1:24 we'll just keep a track of reused,
1:28 make a little set or something like that.
1:32 Actually, let's make it a list
1:33 so we can sort it. for number 1 number 2 in we're gonna use this cool thing
1:38 called "zip", and if you have two lists,
1:41 what it's going to do, if they will get out the way,
1:44 is if you give it two lists,
1:46 it will take an item from one and the other and put them together as a
1:49 tuple. So if I say list one list two,
1:52 I'll get -1000, -1000,
1:55 -99, -99 each time through.
1:57 But they're going to be the values out of the two lists,
2:00 and we're gonna store them into n1 and n2.
2:02 And just so you know what we're doing here we'll print n1 and n2
2:07 and that's not what I want
2:08 to run, let's run it here.
2:09 Here you go. You can see,
2:10 It's just like lining them up side by side,
2:12 but this one comes from list 1,
2:14 and this one comes from list 2.
2:16 So what we want to do is we want to ask,
2:18 Are they equal? Of course they're gonna be equal.
2:21 More importantly, are they the same place in memory?
2:24 So we'll say if the id of n1 is equal to the id of n2
2:28 then we're gonna reuse, go to our reused and append doesn't matter which one
2:34 just one of them to say "this number is reused".
2:40 Then we're gonna print and print out "reused",
2:46 something like this: "Found Reused, n1".
2:51 All right, let's go and just print that and run that real quick and see what happens.
2:54 Ok, this is pretty interesting.
2:56 Look, it goes up to 256 and it starts at -5.
3:01 It's weird, right? So the numbers -1000 up to -6,
3:06 Those are not reused. Those were different allocations
3:09 treated as totally different, unrelated things that just happen to have the same value.
3:13 But from -5, to, scrolled the wrong thing, to 256,
3:19 these are literally the same thing in memory.
3:21 So there will only be one 244 PyLong object pointer in the runtime because
3:27 it's always using it over and over this flyweight pattern.
3:32 So we can also just be a little more clear to make sure we know
3:35 what's happening. So we have a lowest equals
3:38 the min of reused, and the highest is
3:45 the max, and we just print out flyweight pattern from, put a little "f"
4:00 in the front. There we go,
4:02 lowest to highest. Alright,
4:05 one more time. Just like we saw flyweight Pattern is from the numbers -5
4:09 up to 256. This is actually a super cool pattern that you can use in
4:14 your own code. You saw, like,
4:16 python objects and data structures are fairly expensive,
4:20 memory wise. So if you have the idea of like we've got immutable data that's
4:24 reused in lots of places, you could come up with your own concept of a flyweight
4:29 pattern here and optimize that. But,
4:32 you know, that's not really the point here.
4:33 The point is more to talk about the internals of what Python is doing around the
4:37 numbers to prevent them from going totally crazy in terms of how much memory they consume
4:41 because -5 to 256 those numbers appear all the time.