Completely Lost on Event Coordinator Project

I’m on the Event Coordinator project in Generators section of the Intermediate Python course, and I’m completely at a loss as to what to do.

First step is “Modify this function to be a generator function that will yield each read line so that each guest name is yielded each time for the generator.” I have no clue how to do this, and there are no hints in Codecademy, and there isn’t a solution in the project folder.

Does anyone have any pointers?

Honestly, the yield syntax for generators is by far the worst and least intuitive thing I’ve seen in Python yet.

For a basic method of yielding each line in turn from a text file something like the following might suit-

def yield_file_lines(filepath):
    with open(filepath, "r") as textfile:
        for line in textfile:
            # any cleaning/splitting etc. to separate out the 'name'
            yield line  # or name...

In that project I believe you have to parse each line carefully to remove excess whitespace and to separate a guests name and age. Those steps are things you’ll likely have covered before.

Maybe spend a bit of time just playing around with basic generators and revisiting some of the earlier generator lessons if you’re completely lost. The lessons jump very quickly into the co-routine options and .send but generators themselves are exceedingly useful and much simpler than when you’re worrying about state whilst also sending values in. If you’ve come to the project and it’s not clear then it seems like a better choice to review the topic than to continue plowing ahead.

If that’s no good then it might be worth clarifying exactly what’s tripping you up with generators. If you can work out at what point you can no longer track the flow then it might be easier to get useful guidance.

Hi there tgrtim, thanks for replying.

After digging through the forum, I’m happy to say a couple of different posts helped me get this sorted. I’m less happy to report that I had trouble on nearly every step of this project.

Firstly, in step 1, I was confused about this instruction:

Modify this function to be a generator function that will yield each read line so that each guest name is yielded each time for the generator.

I still don’t know whether this is asking me to yield the line read from the text file (yield line_data) or yield the name extracted from that line (yield name). But I opted for the later, and appended yield name to the end of the while loop to make it a generator.

Next, I was bamboozled by the instruction to use a for loop to iterate through the first 10 guests. I kept wondering, shouldn’t this be a while loop with a counter instead? Is this a typo? I now appreciate that the obvious solution was to use range() to iterate over, e.g. for r in range(1, 11). Fair enough.

It wound up getting me wildly off track, though, because instead I tried to combine a for loop with a counter, like this:

generator_object = read_guestlist("guest_list.txt")
counter = 0
for guest in generator_object:
  counter += 1
  if counter <=10:
    print(next(generator_object))

which outputs:

Tonya
Ann
Sam
Kenton
Dixie
Julian
Rose

Only seven names were printed. I was mystified. I added print("Continuing...") right before yield name to try and see if the loop was executing enough, and it was:

Continuing...
Continuing...
Tonya
Continuing...
Continuing...
Ann
Continuing...
Continuing...
Sam
Continuing...
Continuing...
Kenton
Continuing...
Continuing...
Dixie
Continuing...
Continuing...
Julian
Continuing...
Continuing...
Rose

After realizing that my earlier while loops had worked as expected, I realized that I was using next() to advance the iteration while for was iterating over it, resulting in…this weirdness.

The next problem I ran into was the issue of modifying the function to become a generator yielding the name, yet also capable of accepting Jane,35 via .send(), as this later value is more than a name. It’s a comma-separated value such as those that the function has been parsing from guest_list.txt (curious why this isn’t guest_list.csv?). This clearly wouldn’t be as simple as dropping in yield name at the end of the function. Ultimately, the solution would be to add a variable outside the while loop, then test to see if that variable was empty, and if not, format it and set it as line_data, otherwise to take line_data from the text file. Then, at the end of the loop, set the variable equal to yield name.

The lesson on using yield to supply a value from .send() though was confusing to me. As I write this, I’m just now wrapping my head around the fact that when the generator starts, nothing after yield matters, only what is before it (e.g., with var = yield name, the generator only reads val = { value from .send() }). Then, at the end of the loop, nothing before yield matters, only what comes after it (with var = yield name, the loop just “sees” yield name and exits until the next iteration).

So, I admit I had trouble getting this bit, but I wasn’t helped by also trying to diagnose other issues (Should I be yielding just the name or the whole line? shouldn’t this be a while loop? how do I format this string again? where in scope should I set the variable I set yield to? what’s up with this wonky for loop? etc.) at the same time that I was trying to wrap my head around this issue.

These things were largely interrelated as I tried to diagnose and figure out steps 1-4. I finally came across this post which had a solution for everything I had struggled with thus far.

When I got to step 5, I didn’t even understand what it meant. Were these three functions taking inputs? Was each table assigned a single dish, or does each guest select their meal? Was I supposed to use itertools.combinations() from the last section to find out how many combinations of food, table and seat were possible for each guest? Was I making a combined generator? Apparently not, since it plainly stated “Create 3 separate generator functions,” and the hint for this step didn’t allude to a combined function.

I was really at a total stand-still, until I came across this post, whose solution was a little ersatz in places, but shed light on this and further problems.

Step six alludes to the “connected generator seating/food selection we created in the previous step.” Hmm. As I noted previously, I didn’t get any bit of that from the wording or the hint for that step. It was the post above that clued me in that yes, that would indeed be required for the solution.

There were a number of issues here. I was certainly challenged by the material (and this is, after all, an intermediate course). But I think that the wording of this project’s steps was unclear at points. The hints were certainly of little help–the hint on step 2, which entailed figuring out how to refactor the generator so that it would yield the name but accept as input a comma-separated value like Jane,35, simply reminded me to use the send() method to supply a value to yield. Unlike other projects I recall having a solution.py, there was no such help here, by which I might be able at least to deduce what was less than clear to me in the way the steps and hints were worded. And this is my fault for not understanding Codecademy’s interface, but it took me a while before I realized people had posted in the forum about this: I’m accustomed to the link at the end of the steps/checkpoints that links directly the FAQ post, though these are only for lessons, I see.

I’ve filed a content bug on the project linking to this feedback, so perhaps Codecademy will review it. I hope this feedback is helpful.

Finally, if it would do any good to future readers (including myself), here was my final solution:

guests = {} def read_guestlist(file_name): text_file = open(file_name,'r') val = None while True: if val is not None: line_data = val.strip().split(",") else: line_data = text_file.readline().strip().split(",") if len(line_data) < 2: # If no more lines, close file text_file.close() break name = line_data[0] age = int(line_data[1]) guests[name] = age val = yield name guestlist = read_guestlist("guest_list.txt") for i in range(1,11): print(next(guestlist)) print(guestlist.send("Jane,35")) for g in guestlist: print(g) print("\n") whoIsOver21 = (guest for guest in guests if guests[guest] >= 21) for g in whoIsOver21: print(g) def table_one(): for i in range(1,6): yield ("Chicken", "Table 1", "Seat {}".format(i)) def table_two(): for i in range(1,6): yield ("Beef", "Table 2", "Seat {}".format(i)) def table_three(): for i in range(1,6): yield ("Fish", "Table 3", "Seat {}".format(i)) def combined_tables(): yield from table_one() yield from table_two() yield from table_three() table_assignment = combined_tables() def assign_tables(list_of_guests): for name in list_of_guests: yield (name, next(table_assignment)) guest_assignment = assign_tables(guests) for person in guest_assignment: print(person)
1 Like