Python Forum
"Travis" guest list name checker (Ziyad Yehia Udemy course)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
"Travis" guest list name checker (Ziyad Yehia Udemy course)
#1
I'm taking a Udemy course (not for credit, just for fun) but I would still like to treat this as a homework exercise so for experienced forum members, please do not solve the problem for me. All I am asking is for hints and tips.

The task involves verifying the contents of a list using conditionals. For a full explanation of the purpose of this program and for instructions from the teacher, you can read them in the README on my GitHub repo (second paragraph from the bottom).

I kinda got the program to run. It used to meet the requirements set out by the instructor. But I am now taking the project in a new direction by consolidating the operations into two separate functions (one called ‘main’ and the other called ‘check’). It is extending this script that I am encountering a Name Error and a Type Error.

Here is my script so far:

#!/usr/bin/env python3
# This third iteration splits the code into two different functions

def main():
    """
    Initializes the two primary variables and returns them for future use
    """
    guest_list = ["Justin Trudeau", "Joseph Stalin", "Caesar", "Nero",]
    user_name = input("What is your name? Please spell it in full! >>  \n")
    return (guest_list, user_name)


def check(placeholder):
    """
    Verifies the user name input and determines if in guest list
    """
    if user_name in guest_list:
        print(f"Welcome, {user_name}!")
    if user_name not in guest_list:
        print(f"Hi {user_name}, but unfortunately you are not in the guest list.")
        include_proposition = input("Would you like to join us anyways? Please enter a Yes or a No >> \n")
        if include_proposition == ("Yes", "Y", "y"):
            guest_list.append(user_name)
            print(f"Thanks, {user_name}! You've been added. Please enter.")
        if include_proposition == ("No", "N", "n"):
            print("OK! Have a good night then, my friend!")
        else:
            print("Sorry, I didn't get that. Please enter your selection again")


if __name__ == "__main__":
    placeholder = main()
    check(placeholder)
Notice at line 13 I pass the placeholder variable (which I initialize at the end of the script) below the if name conditional. Here is NameError the traceback:

Quote:$ python script3.py
What is your name? Please spell it in full! >>
Matt
Traceback (most recent call last):
File "script3.py", line 33, in <module>
check(placeholder)
File "script3.py", line 17, in check
if user_name in guest_list:
NameError: name 'user_name' is not defined

I figure the check() function requires user_name and guest_list so I tried replacing the placeholder as a parameter at line 13 with guest_list, user_name which returns a TypeError:

Quote:$ python script3.py
What is your name? Please spell it in full! >>
Matt
Traceback (most recent call last):
File "script3.py", line 33, in <module>
check(placeholder)
TypeError: check() missing 1 required positional argument: 'user_name'

Here are my two questions:
  1. How do I call both functions (main() and check()) properly so as to avoid these tracebacks?
  2. What do you call the Python convention with if __name__ == "__main__":? When I Google "if __name__ == "__main__"" there is a very detailed and thorough Stack Overflow question and answer which explains very clearly how, why and when to use if __name__ == "__main__": however it doesn’t actually say what this Python convention is called. So what do you call this?

For my future reference, this Udemy instructor Ziyad Yehia calls this the "Travis" application. This is the fourth project under the "Python Datastructures" section. The course is titled "The Python Bible: Everything You Need to Program in Python"
Reply
#2
So, what type does main() return? That is the type assigned to placeholder in the dunder main. What type does the check() function require as an argument? Note that you can't determine that by the type of placeholder from main, and using the same name for the argument as the variable in main can be confusing (and therefore recommend avoiding, it comes back to bite you - if you had used a different name the problem would be obvious).
Reply
#3
Thank you @jefsummers for your advice.

(Aug-23-2019, 01:04 AM)jefsummers Wrote: So, what type does main() return?

Right now the main() function returns a variable as (placeholder) which represents two other variables: guest_list and user_name. When I call the main() function under the __name__ guard, I am assigning it to two variables (which I gather is technically impossible because a variable can only represent a single other variable and not two). So this is a major problem.

(Aug-23-2019, 01:04 AM)jefsummers Wrote: That is the type assigned to placeholder in the dunder main.

I’m not sure what you mean by the dunder main.

(Aug-23-2019, 01:04 AM)jefsummers Wrote: What type does the check() function require as an argument?

The check() function requires two variables as its argument: both guest_list and user_name which I thought I had assigned together as placeholder. In my next iteration of this script (copied below), at line 13 where the check() function is defined, I have swapped out placeholder and am now using guest_list and user_name because these are the two required arguments according to Name Error in the trace back.

Here are the changes I have made to my script since my previous post:
  1. At line 10 I return just guest_list, user_name without brackets because previously with brackets, it returns a tuple. I don’t want a tuple.
  2. At line 13 where I define the check function, instead of placeholder I pass in guest_list, user_name because this is what the function actually needs
  3. Under the name guard at the bottom, I keep placeholder assigned to main() but when I call check() I include the two required parameters: guest_list, user_name

Quote:Note that you can't determine that by the type of placeholder from main, and using the same name for the argument as the variable in main can be confusing (and therefore recommend avoiding, it comes back to bite you - if you had used a different name the problem would be obvious).

I am struggling to manage these variable assignments and pass them as arguments.

I feel like I have made a valiant attempt here to accomplish what I set out to achieve and I have come pretty close. The solution I need is so trivial and minor, I think I am at the point where I am ready to see the full solution from a forum member like @jefsummers or someone else demonstrating how to manage functions and variable assignments in the context of my script.

Here is my slightly altered script that I am working with now with the three changes noted above:

#!/usr/bin/env python3
# This fourth iteration of this script splits attempts to resolve the Type + Name Errors

def main():
    """
    Initializes the two primary variables and returns them for future use
    """
    guest_list = ["Justin Trudeau", "Joseph Stalin", "Caesar", "Nero",]
    user_name = input("What is your name? Please spell it in full! >>  \n")
    return guest_list, user_name


def check(guest_list, user_name):
    """
    Verifies the user name input and determines if in guest list
    """
    print(guest_list, user_name)
    if user_name in guest_list:
        print(f"Welcome, {user_name}!")
    if user_name not in guest_list:
        print(f"Hi {user_name}, but unfortunately you are not in the guest list.")
        include_proposition = input("Would you like to join us anyways? Please enter a Yes or a No >> \n")
        if include_proposition == ("Yes", "Y", "y"):
            guest_list.append(user_name)
            print(f"Thanks, {user_name}! You've been added. Please enter.")
        if include_proposition == ("No", "N", "n"):
            print("OK! Have a good night then, my friend!")
        else:
            print("Sorry, I didn't get that. Please enter your selection again")


if __name__ == "__main__":
    placeholder = main()
    check(guest_list, user_name)
Even with these changes, here is the NameError still showing:

Quote:$ python script4.py
What is your name? Please spell it in full! >>
west
Traceback (most recent call last):
File "script4.py", line 34, in <module>
check(guest_list, user_name)
NameError: name 'guest_list' is not defined
Reply
#4
As a convention main() function is used in top-down style of coding where all 'the action' takes place. It's defined at top and all the functions it uses below.
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#5
You are really really close.
First the slang - dunder means double underscore. So your line 32 would be read "if dunder name equals dunder main". Sorry for using slang.
In that script (the dunder stuff) the variable "placeholder" is filled with 2 items through the call to main. In the next line you call check on what you know should be in "placeholder" but the python interpreter does not. You need to add 2 lines right before you call check:
    guest_list = placeholder[0]
    user_name = placeholder[1]
Then that part works.
However, you have another problem - if you enter a name not on the list it asks if you want to be added. The problem is the comparison in lines 23 and 26. The person would need to enter a set of all 3 options to have that equal your set. I think you want to know if the response is in the list, not equal to the whole list which is what you are doing now. Fix those and I think you have a working version.
Reply
#6
This would do it nicer, but as already mentioned you should rename the main() function e.g. into get_guests() or so.
guest_list, user_name = main()
def get_guests():
    """
    Initializes the two primary variables and returns them for future use
    """
    guest_list = ["Justin Trudeau", "Joseph Stalin", "Caesar", "Nero",]
    user_name = input("What is your name? Please spell it in full! >>  \n")
    return guest_list, user_name
 
 
def check(guest_list, user_name):
    """
    Verifies the user name input and determines if in guest list
    """
    print(guest_list, user_name)
    if user_name in guest_list:
        print(f"Welcome, {user_name}!")
    if user_name not in guest_list:
        print(f"Hi {user_name}, but unfortunately you are not in the guest list.")
        include_proposition = input("Would you like to join us anyways? Please enter a Yes or a No >> \n")
        # THE NEXT LINE DOES NOT WORK! DO IT AS 3 LINES ABOVE!
        if include_proposition == ("Yes", "Y", "y"):
        # ------------------------------------------
            guest_list.append(user_name)
            print(f"Thanks, {user_name}! You've been added. Please enter.")
        # THE NEXT LINE DOES NOT WORK! SEE ABOVE!
        if include_proposition == ("No", "N", "n"):
        # -----------------------------------------
            print("OK! Have a good night then, my friend!")
        else:
            print("Sorry, I didn't get that. Please enter your selection again")
 

def main():
    guest_list, user_name = get_guests()
    check(guest_list, user_name)

if __name__ == "__main__":
    main()
Reply
#7
@perfringo: Thank you for explaining that the main() function is where the main actions or operations of a script take place.

@jefsummers: You said: “the variable ‘placeholder’ is filled with 2 items through the call to main”. I thought it was impossible to have one variable contain or represent two other variables at the same time? I have misunderstood here.

@ThomasL: Thanks for taking the time to refactor my script almost from scratch and iron out the issues. I have added some further polish. Here is my script now:

#!/usr/bin/env python3
# This iteration is mostly based on the help provided by more than one Python Forum members here: https://python-forum.io/Thread-Travis-guest-list-name-checker-Ziyad-Yehia-Udemy-course

def get_guests():
    """
    Initializes the two primary guest and user variables and returns them for future use
    """
    guest_list = ["Justin Trudeau", "Joseph Stalin", "Caesar", "Nero",]
    user_name = input("What is your name? Please spell it in full! >>  \n")
    return guest_list, user_name

def check(guest_list, user_name):
    """
    Verifies the user name input and determines if in guest list
    """
    if user_name in guest_list:
        print(f"Welcome, {user_name}!")
    if user_name not in guest_list:
        print(f"Hi {user_name}, but unfortunately you are not in the guest list.")
        guest_list.append(user_name)
        print(f"But I have added you, {user_name}! You are welcome to enter now.")

def main():
    guest_list, user_name = get_guests()
    check(guest_list, user_name)

if __name__ == "__main__":
    main()
It runs beautifully without a traceback.

I have another question: @perfringo says that the main function should be defined that the top and invokes all the functions below it. However in @ThomasL’s suggested script, main() is positioned below the two functions. Would either of you be able to clarify this?

Going forward I’m considering adding a while loop to give the end user the choice of being added to the original guest_list. I kinda tried adding this functionality previously without a while loop but it crashed and burned. I’ll start a fresh forum thread when I tackle the while loop feature.
Reply
#8
(Aug-22-2019, 11:09 PM)Drone4four Wrote: For a full explanation of the purpose of this program and for instructions from the teacher, you can read them in the README on my GitHub repo (second paragraph from the bottom).

I took a closer look and as a result I am puzzled. Instructions are:

Quote:This programs will have a list of known users. Every time it runs, it will prompt the user to enter his or her name. If your name is present, the program will welcome you and ask if you wish to be removed from the list. If it doesn't recognize you, it will ask the user if he or she would like to be added to the list.

I don't understand why invent functionality which is not required? Fully functional code which complies to objectives above is very simple. If this is not what is expected it may indicate that either (a) quality of this course is questionable (b) you didn't include full description of the task.

Following code does exactly what is described:

- have list of known users
- prompts the user enter name
- if name present will ask if you wish to be removed
- if name not recognized will ask would you like to be added

known_users = ['Guido', 'Raymond', 'David']
user_name = input('Enter your name: ')
if user_name in known_users:
    print(f'Hello {user_name}! Do you want to be removed from the list?')
else:
    print('Do you want to be added to the list?')
Nowhere in description of task there is adding or removing names from list etc. From Python Zen: "In the face of ambiguity, refuse the temptation to guess."
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#9
In line 7 you return guest_list, user_name. You are returning a tuple. From IDLE:
>>> foo = "alpha","beta"
>>> print (foo)
('alpha', 'beta')
>>> print (type(foo))
<class 'tuple'>
The tuple contains two items. In the above, they are two strings. In your case they are guest_list and user_name.
For a better description on tuples see https://docs.python.org/3.7/tutorial/dat...-sequences
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Creating guest list manager nickster11 1 2,847 Feb-08-2021, 02:44 PM
Last Post: deanhystad
  Password Checker Assignment mcostello 1 5,073 Nov-14-2020, 07:54 AM
Last Post: DPaul
  Palindrome checker case sensive edwdas 3 2,637 Nov-07-2019, 05:57 PM
Last Post: nilamo
  Syntax checker BZA 4 3,191 May-16-2019, 06:40 PM
Last Post: BZA
  Spell Checker Liquid_Ocelot 1 3,189 May-07-2017, 11:28 AM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020