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)