Home > Enterprise >  List Retains Data But Not String?
List Retains Data But Not String?

Time:07-19

So I was doing some practice exercises from a Python programming book, we were supposed to be manipulating a list. I decided to define some functions for this task, and my first function was the following:

guest_list = []
guest_list_text = ""

def invite_guests():
    user_choice = input("Would you like to add a guest to the guest list? ").lower()
    while user_choice == "yes":
        """Initially I used an if/else statement in this while loop, but I realized I didn't need
            them for this task."""
        guest_list.append(input("Who would you like to invite? ").title())
        guest_list_text = ", ".join(guest_list)
        print("Great! I'll add them to the list!")
        print(f"So far you've invited {guest_list_text} to the party.")
        """We're gonna leave this as is for now; what matters most right now is getting in my reps, 
             not perfect code. We learned how to use join here. Create an empty string, then assign
             the list you want to join to it with join--what's inside the quotes will join the items."""
        user_choice = input("Would you like to add another guest to the list? ").lower()

    print(f"I've sent the following message to {guest_list_text}: \n\tHello! I'm throwing a dinner party, would you like to come?")

    return guest_list_text

So I had the list "guest_list" and the string "guest_list_text", I think you would call them global variables because they are outside of any function? Well, later I tried to use guest_list_text inside of a new function, with and without using it as an argument in that function. I tried to print a message:

print(f"Sending an update to {guest_list_text}: Good news everyone! We've found a bigger table!\n" \
          "That means I'll be inviting more people!")

And the output was: "I've sent the following message to :" To fix this, I had to type in, inside the new function:

guest_list_text = ", ".join(guest_list)

So that tells me that for some reason, the list retained the data from the first function, but the string did not. Can anyone explain this to me?

CodePudding user response:

Python understand that guest_list is global, because you use it inside the function (guest_list.append(...)) without a local declaration, but for guest_list_text is different, because you are assigning a value to it in guest_list_text = ", ".join(guest_list) but python understand it as a local variable declaration, for telling python that you want to treat guest_list_text as a global variable, you can use global guest_list_text, like this:

guest_list = []
guest_list_text = ""

def invite_guests():
    global guest_list_text
    user_choice = input("Would you like to add a guest to the guest list? ").lower()
    while user_choice == "yes":
        """Initially I used an if/else statement in this while loop, but I realized I didn't need
            them for this task."""
        guest_list.append(input("Who would you like to invite? ").title())
        guest_list_text = ", ".join(guest_list)
        print("Great! I'll add them to the list!")
        print(f"So far you've invited {guest_list_text} to the party.")
        """We're gonna leave this as is for now; what matters most right now is getting in my reps, 
             not perfect code. We learned how to use join here. Create an empty string, then assign
             the list you want to join to it with join--what's inside the quotes will join the items."""
        user_choice = input("Would you like to add another guest to the list? ").lower()

    print(f"I've sent the following message to {guest_list_text}: \n\tHello! I'm throwing a dinner party, would you like to come?")

    return guest_list_text

CodePudding user response:

As stated in Rodrigo Llanes' answer, your code fails because you are manipulating a global variable in the local scope of the invite_guests() function. Declaring that variable as global inside the function will solve the problem as you were expecting. However, global variables are, in many cases, a bad practice since they produce an implicit declaration: you change the value of a variable without actually declaring your intention of doing so. In opposition, for example, of what you did when declaring guest_list = []. This may lead to your program producing an unexpected output, that can be difficult to debug.

There's an interesting discussion about that here.

So, I want to propose this other approach:

guest_list = []
guest_list_text = "There're no guests in the list yet!"

def invite_guests(guest_list):
    guest_list_text = ""
    user_choice = input("Would you like to add a guest to the guest list? ").lower()
    
    while user_choice == "yes":
        guest_list.append(input("Who would you like to invite? ").title())
        guest_list_text = ", ".join(guest_list)
        print("Great! I'll add them to the list!")
        print(f"So far you've invited {guest_list_text} to the party.")
        user_choice = input("Would you like to add another guest to the list? ").lower()

    print(f"I've sent the following message to {guest_list_text}: \n\tHello! I'm throwing a dinner party, would you like to come?")

    return guest_list, guest_list_text

And then you can call the function like this:

guest_list, guest_list_text = invite_guests(guest_list)

Now you could use the same function with more than one list of guests. Note that is not necessary for the list and the text of the list to be called the same way they're called inside the function. You could do, for example friends_list, friends_list_text = invite_guests(friends_list).

But also you have a line that explicitly says, "hey python, create a list of guests now!". Which is going to make things way easier if something doesn't work as expected.

  • Related