Thursday Mornings With Python, Part 6

Thursday Mornings With Python, Part 6

It's a Thursday morning with Python and unusually I'm starting out on a train as well. BUT THERE IS ALSO A MASSIVE PLOT TWIST. I hope to share it in a picture later today lol. If my costume is still intact(ish). I just need to buy 3 rolls of cellotape when I get to the train station.

Just you wait and see...

A pink dreamscape image with all of the python content Susanna completed today

Generator Expressions

This is so amazing omg. This is so much simpler than the generator function thing and I have been using them for ages anyway. It was good to remember the syntax. There is a great table on list comprehensions vs generator expressions but let me write it up in my own words anyway please thanks.

Generator expressions are wrapped in brackets, whereas lists are wrapped in square brackets.

Generator expressions return a "newly defined iterable object", whereas list comprehensions return a, well, list. A new list. I want to dwell a bit more on this "newly defined iterable object" but I also just want to write some code.

The main thing about generator objects is that they cannot be accessed directly. I know this from my Codewars days - they usually have to be turned into something else.

For example, we can pass it into a for loop. And it works just fine. Yay!

Here is some code that I wrote on the course please thanks:
def cs_generator():
  for i in range(1,5):
    yield "Computer Science " + str(i)

cs_courses = cs_generator()

for course in cs_courses:
  print(course)

cs_generator_exp = ("Computer Science " + str(i) for i in range(1,5))

# Another way of doing this would be

cs_generator_exp_2 = ("Computer Science {}".format(i) for i in range (1,5))

for course in cs_generator_exp:
  print(course)

for course in cs_generator_exp_2:
  print(course)
And here is the output: 
Computer Science 1
Computer Science 2
Computer Science 3
Computer Science 4
Computer Science 1
Computer Science 2
Computer Science 3
Computer Science 4
Computer Science 1
Computer Science 2
Computer Science 3
Computer Science 4
Omg, I desperately need to buy some cellotape at Victoria, please, thanks. I can't wait!!! Onto the next thing.

Generator Methods: send()

"The .send() method allows us to send a value to a generator using the yield expression.

If you assign yield to a variable the argument passed to the .send() method will be assigned to that variable.

Calling .send() will also cause the generator to perform an iteration."

This is like the most complicated thing that I have ever seen.

So we can pass this through to a yield. Omg I just don't get it omg.

Time to write some code...

"The .send() method can control the value of the generator when a second variable is introduced. One variable holds the iteration value and the other holds the value passed through yield."

Asking ChatGPT for help and begging

  • .send() lets you send a value into a generator at a specific point.
  • It's like next(), but with an added power: 
    • It lets you change a variable inside the generator mid-way. 

Learning from the Coding Example

Practical use cases are the best so here we are.

Let's say I am a teacher. I have my list of students.
Every time I go through filling out a grade for a student I get the generator to output my current student's ID. The first time I sit down to do it it's okay; I start from 0 on the first iteration of the loop and then when we perform the loop the counter goes up by one every time.

This is fine but I have seen teachers mark - my mum was an external examiner for many years. Let's say we get to student 22. Then we need a coffee. Or a break. To come back to it the next day maybe.

So we would like the loop to start again at 23. So how are we gonna do this please? Thank you. Well this code demonstrates that... I still don't get entirely how or why.

I will go through the rest of the lessons at a reasonable pace to try and understand what I should go through with my senior today.

Oh I know there are also YouTube videos!

(But will stick to the exercise for now - also note to myself halfway through: ohhhhh omg yeah I get it. We want to send a specific value to ourselves. Maybe I get it now. Maybe).

Oh got it so - we only use this send() method if we get kicked out of our loop. Otherwise we just can and do continue to use next. So this is why - as you will see in a minute - my final for loop checks if i == 1. We only need to use .send() if i == 1. Otherwise we can just presumably continue? My notes make no sense today but don't worry I am just processing things and they are for me.

Wait no I don't get it again omg no I am so lost arrrrgh. So this is just a function that if you get lost at 25 you can pick up from 25. But what if you want to start from somewhere else please? Arrrrrrrrgh.
MAX_STUDENTS = 50

def get_student_ids():
  student_id = 1
  while student_id <= MAX_STUDENTS:
    # Write your code below
    n = yield student_id
    if n is not None:
      student_id = n
      continue 
    
    student_id += 1

student_id_generator = get_student_ids()
for i in student_id_generator:
  # Write your code below
  if i == 1: 
    i = student_id_generator.send(25)
  
  print(i)

Well I have no idea what I just did. What if we want to start from 29 - do we have to hard code it? So basically if it drops back to 1 (why not 0?) we can get it back to 25. But how. Not even by calling the function. Just by calling the for loop.

I have never understood anything less in my life - as a JavaScript developer too I was taught not to take while loops too seriously. Gonna asked Chat GPT what it thinks of this section please do see if it gets anything but if not then next lesson I guess. 

Oh okay - points from ChatGPT: 
  • My code DOES start from 1 and not from 0 so that is my bad. 
  • I could just swap the 25 to any other value in the code and it would still work please thanks

Wise words from ChatGPT

"Generators, yield and send() have different behaviours than standard functions and loops, but they offer powerful ways to manage state and iteration in Python." WOW. WOW WOW WOW. "Generators, yield and send() have different behaviours than standard functions and loops, but they offer powerful ways to manage state and iteration in Python."

They "OFFER POWERFUL WAYS TO MANAGE STATE AND ITERATION IN PYTHON". WOW.

Generator Methods: throw()

"The generator method throw() provides the ability to throw an exception inside the generator from the caller point. This can be useful if we need to end the generator once it reaches a certain value or meets a particular condition." 

I need to try and put things into my own words please a bit more often.

In my own words please... thanks.

Okay so this reminds me of a break keyword. So what's the difference hmm.

OMG THIS JUST THROWS EXCEPTIONS

SO I HAD TO WRITE IT OUT TO UNDERSTAND IT PLEASE BUT NEVERMIND I GET IT NOW THANKS.

SOMETIMES I HAVE TO WRITE THINGS OUT TO GET IT FIRST. BUT I UNDERSTAND NOW THANKS.

HENCE JUST ONE MAIN QUESTION... THIS IS WHY I CAN'T READ.
def student_counter():
  for i in range(1,5001):
    yield i

student_generator = student_counter()
for student_id in student_generator:
  # Write your code below:
  if student_id > 100:
    student_generator.throw(ValueError, "Invalid student ID")
  
  print(student_id)
Okay so:
  • We throw the error whenever we want to exit the loop
  • We either might want to throw one when the generator either reaches a certain value or meets a certain condition
  • Had a quick chat with my manager about the above two methods and we agreed they are not too useful as they are quite niche but we had an amazing lesson on yield

Generator Methods: close()

  • This is so easy and super super simple. It just ends the loop.
  • As chat GPT says: the purpose of .close() is to "terminate a generator gracefully."
  • Looking at the code example I can see that this closes the loop - and raises an exception if you try and call next on it please thanks.
"The .close() method works by raising a GeneratorEcit exception inside the generator function."

Questions

notes to self, rather
  • Show first blog post (Tues)
  • Show this blog post - explain that I did generator expressions and that was fine (Comfort zone)
  • Explain send() and how this was not comfort zone at all and how I still don't get it wow
  • Explain throw()
  • Problem - I am not getting the point in most of this code please - thanks. For the last 2 - why would we use it?

Comments

Popular posts from this blog

Hello World

Yosemite

Where To Hide A Star