Python for the .NET Developer Transcripts
Chapter: The Python Language
Lecture: Python closures

Login or purchase this course to watch this video and the rest of the course contents.
0:00 We saw this idea of closures in C# was really interesting and powerful. Does Python have something like it? Let's find out.
0:08 Over here, let's create one of these functions that creates this counter, this closure. So, we'll say def create_counter and it takes a start_val
0:18 and a counter_id. So what did we do? Well, we had a print statement, and then what did we do? We defined a delegate type, didn't emphasize that
0:27 we had to create a delegate type and then we defined a delegate instance. Python you have this idea of these delegates as well
0:34 but it's much, much simpler. You just define a function with exactly the same syntax but indented so it's defined here.
0:43 We'll create a counter, which is a void function say has a start, equals a start_val it's going to start from that. Maybe, it's going to increment.
0:54 We called it start before but it's kind of badly named so we said every time you call it we're going to increment
0:58 this by one, and then we're going to print out some kind of formatted string. Like this, we're going to say the current counter_id is this
1:07 and we started at this and now our current value is whatever we've incremented it to. Notice though, there's something a little bit
1:13 funny going on here. We have these values that seem to be captured just fine but this increment, there's something off with it
1:21 it says we don't know what that is. And in order to tell this function it's allowed to capture local variables or even just to try to print it out
1:29 you have to use a new keyword, a nonlocal inc and that says I'd like you to reach up to this intermediate scope, it's not global
1:38 it's not defined here, and work with it. Sometimes you have to use nonlocal, sometimes you don't it's not entirely obvious when that is true
1:46 but down here we can return count, counter not like this, that would call it, just the name. So we're turning this function that was defined right here
1:56 and it's actually going to do closure on these values just like before. So let's go over here and say counter1 = create_counter, start value
2:05 and we have 7 and the id was 1. So let's just call counter a few times like that we run this, and we run the right thing. Look at that.
2:17 Counter with id 111 it's start value is 7 now it's 8, now it's 9, now it's 10. Pretty cool, right? So exactly like C#, except for we didn't have
2:28 to jump through hoops to specify the return type here of whatever this delegate type that we're going to define we just said no, here's a function
2:36 really more generally, there's something. Here's a thing that can be called 'cause classes and other objects can implement
2:41 something along those lines as well and then we just passed it back. We also just had another one that was at -100
2:47 and this was id 2, that we said counter2, counter2 and then we did that three times. Run it one more time, okay. Counter id 1, 1 and 1
2:58 still goes from 7 to 8, seven to 9, 7 to 10. And number 2 is going from -100 to -99 to -98, to -97, exactly like the C# closure
3:09 that we had before. Cool, right? So, same thing if you have lambda expressions or those little types of things
3:15 you can use closure to capture those values into interesting things. But just be careful because these values are remembered
3:22 they don't reset like normal functions.

Talk Python's Mastodon Michael Kennedy's Mastodon