Locked learning resources

You must own this product to watch this lesson.

Locked learning resources

You must own this product to watch this lesson.

Using Advanced Generator Methods

This lesson is from the Real Python video course by Christian Mondorf.

00:00 After telling you about the basic syntax of generators and why and how you would use them in the last video, I think we’re ready to move on to some more advanced generator methods.

00:10 There are three of these, which you should really be aware of: send(), throw(), and close(). I’m going to illustrate them using some sample code.

00:19 Let’s switch over to the IDE. So here we are, and there is a function here, which detects palindromes. A palindrome is a number or a word which is read the same way forwards and backwards.

00:31 So, examples of number palindromes could be 121, 111, 141, 747, and so on. Examples of words are things like level, radar, and so on. Okay. So, you don’t need to understand how this function works exactly in detail, just at a very high level. Here we’re checking if an input number has a single digit and if it does, then we skip it.

00:58 I guess we could argue whether or not a single digit is a palindrome, but they’re kind of special cases. Then here on lines 5 to 9, we are actually reversing the number and checking if the number itself is the same as its reversed version. If that is the case, we will return True. If not, we will return False. Okay.

01:22 This is how we are going to make use of our function. So, I’ll explain this in steps. At the top, you have the infinite_palindromes() generator.

01:32 And how can you tell this is a generator? If you answered, “Because there’s a yield keyword,” then you’re right. This is a function with a yield keyword, and therefore, it’s a generator.

01:44 Let’s step through this. We start by setting a variable num to 0 and then, while True:so this is an infinite loop—

01:53 we’re giving num to is_palindrome() and checking whether or not it’s a palindrome. If it is, it gets yielded back to us, remember? This is returned, and infinite_palindrome() keeps state.

02:05 Now, this line here is quite interesting because you can see that yield is to the right of an assignment operator. This works together with the code down here, so here we’re starting our infinite_palindromes() generator,

02:20 we’re iterating through it, we’re printing out numbers which turn out to be palindromes. Then, if they turn out to be palindromes, we are extracting their length, so the number of digits in the palindrome, and here we’re adding a leading 1 to it.

02:36 So if 121 is a palindrome, then we will start our next search from 1000.

02:42 Because there are three digits in 121, we’re putting 1 in front of that, that gives 1000. What’s interesting here is the send() method.

02:50 This is the first of the advanced methods I wanted to show you. What this is doing is this is sending this to our generator, and the way it does that is—remember we started the generator here—it ran until it found one palindrome.

03:06 When it’s done that, we extract the length of the palindrome, put a 1 in front of it, so for a three-digit palindrome, that’s three 0’s with a 1 in front of them, or 1000.

03:15 And then this send() is sending that value, so 1000, here in the place of num. And that’s how yield, in this case, is playing a double role. On the one hand, it returns a value to us, or yields a value to us. But on the other hand, it works as a kind of placeholder where we can slide a new value into it.

03:35 So now i has a value of 1000, and that’s the value which is then fed into the palindrome detector, and from where we will start looking for the next palindrome in the sequence.

03:46 Let’s try running this. I’m going to make the terminal a bit bigger so it’s easier to see.

03:54 And there you can see it’s giving us palindromes and each time it’s finding a palindrome which is one digit longer than the previous one. At first it’s quite quick, and then the sequences become longer and longer, so you can see that it starts to slow down, but it’s still running.

04:09 If we give it a few seconds, it will give us another palindrome, or we can just interrupt it and move on. Let’s do that. Okay. That was the send() method.

04:18 The send() method allows you to slip a value into the last yield statement where you stopped and, keep in mind, you can have more than one yield statement.

04:27 In our example, we only had one. The next thing we’re going to look at is the throw() method. What throw() allows us to do is to throw an exception in a generator.

04:37 I’ll show you how this works in practice. Let’s go back to the IDE. Let’s enlarge the code editing part again so that this is easier to read.

04:47 Now, remember, here in digits we are extracting the length of the palindrome which we just found. I’m going to modify this a bit. And what I’m going to do is I’m going to add a check here, whether or not we have found a palindrome which has five digits.

05:02 So 121 would have three digits, 1221 would have four, and I guess 12421 would have five. And then that would trigger this line because this would be True and it would execute this method.

05:17 So, what this is doing is that the throw() method is causing the generator to throw an exception and we’re specifying which exception we want. So I’m telling it I want a ValueError and I want the error message to read, "We don't like large palindromes". I’m going to save this, I will enlarge the terminal again, and I’m going to run it. Well, here at the terminal first.

05:43 And you can see I got a first palindrome 11, then 111, then 1111, then 10101 has five digits, and we got this error message.

05:57 The next and final advanced method I’d like to talk about is the close() method. As the name suggests, this allows us to close a generator.

06:06 So remember that generators keep state between each time they’re being called and close() causes the generator to lose state. It sort of evaporates the way a normal function would if it hit a return statement. So coming back to the IDE, if you’ll remember from a minute ago, I had introduced this throw() method here.

06:25 I’m going to replace this with just a simple close(), Save,

06:31 and then watch. When I run this, instead of giving us an exception, the generator will close. I’m going to clear the terminal and then run this.

06:40 And you can see that the generator has given us a StopIteration exception, which is what normally happens when a generator is exhausted. So close() caused the generator to stop and behave as if it had exhausted its sequence.

06:54 So those were the three advanced generator methods that I wanted to show you. First, there’s send(). send() allows you to send a value into where the generator last stopped, so where the yield statement was.

07:06 Something to keep in mind is that you need to have reached a yield statement, so the generator needs to be initialized before you can send something to it.

07:14 Then, throw() allows you to cause the generator to throw an exception. You can define which error type you want and which error message you want.

07:22 Finally, close() allows you to close a generator. It behaves by returning a StopIteration exception. So, it behaves as if it had exhausted its sequence, which it’s generating.

07:33 Okay, that’s it for this video. In the next video, I’m going to be showing you how to create a data pipeline using generators. I’ll see you there!

You must own this product to join the conversation.