Passing variables through multiple functions python - python

So I'm trying to make a function that prompts the user for an option, and depending on which option it does something to the information.
Optionone() basically asks the user for information for a single contact, and every time this contact is filled out it creates a list in a list full of the diff contacts.
In optionthree() I am trying to ask a user for a contact they want to display. So once they type in the name of the contact, the code should display the entire list consisting of the contact's information (name, address, phone, email).
I've excluded the other options that are irrelevant to this problem.
contact = []
def optionone():
contactinfo = []
name = str(input("Name: "))
address = str(input("Address: "))
phone = str(input("Phone: "))
email = str(input("Email: "))
contactinfo.append(name)
contactinfo.append(address)
contactinfo.append(phone)
contactinfo.append(email)
contact.append(contactinfo)
contactinfo = []
This is the optionthree function.
def optionthree(contactinfo):
search = input("Name of contact: ")
if search in contactinfo:
print("This is what I'm trying to figure out")
else:
print("There is no contact with that name in your address book.")
return contactinfo
And the main menu function
def menu():
option = int(input("""
Menu Options:
1. Add new contact
2. Display address book
3. Search for contact
4. Modify contact
5. Delete contact
6. Exit
Choose an option: """))
if option == 1:
optionone()
elif option == 3:
info = optionthree(contactinfo)
main()
Right now, when I run this in terminal, it tells me that I'm referencing to the variable contactinfo before it is assigned. The whole concept of parameters and passing variables through functions is very confusing for me; what is wrong in this code?

you use contactinfo in the main function, but didn't define it in the main function. I notice you define a global variable "contact". Not sure if it is the same variable

It looks like you are attempting to reference contactinfo before it gets assigned any values. If you need to have executed option 1 before executing option 3, then you may want option 3 to first check if contactinfo exists. If it doesn't exist, I would suggest writing that line as the following:
info = optionthree(optionone())

Here at Stack Overflow, we handle one problem at a time. In this case, the immediate problem is the undefined variable. Please handle the info look-up in a separate posting, if you still can't figure it out.
I'm going to get rid of extra information for illustration. It's a good programming technique: take little steps. First, we're going to get a name only into the list and be able to find it. You have almost everything hooked up.
The basic principle to remember is that each function has its own "name space" (directory of variables and values). Functions communicate with each other through the parameter list and return values. Yes, there are global variables, too. For now, don't use them.
The purpose of option_one is to add a name to the info list, and make the change available to the main program. You forgot the last part: you have to send back the updated list when you're done:
def option_one(contact_list):
name = str(input("Name: "))
contact_list.append(name)
print("OPT 1 contact_list", contact_list) # trace what you do for debugging purposes.
return contact_list
def menu():
# Menu text omitted
master_list = []
if option == 1:
master_list = option_one(master_list)
print("MAIN ", master_list)
elif option == 3:
info = option_three(master_list)
menu()
Make your main program "own" the master list -- the option functions merely get a copy, do their "thing", and return the updated list (if needed). The main program has to initialize that list, master_list, and hand it off to each chosen function.
Each function has its own little world: what it got from the calling program, the local variables it creates, and what it hands back when it's done. Each routine can call that contact list by whatever local name it chooses; I've called it contact_list (as you did, but with "Pythonic" punctuation).
Output:
Choose an option: 1
Name: Mark
OPT 1 contact_list ['Mark']
MAIN ['Mark']

Related

Python adding unique string into array

ok this is more of a conceptual question, but if i have an array of strings, how can i make a condition where i have a program that tracks a chat and prints out the players name, how can i make a condition where i have a loop that prints the players name every time they chat once i turn on the program, but if they chat again, and my program recognizes the familiar name, it wont print their name out again, essentially only printing out that persons name once
userName = "ThePlayersName" # constantly changing
nameTracker = []
if userName not in nameTracker:
print(userName)
I understand the program is wrong, but just assume 'UserName' is constantly changing and the userName is being added to the array, or another way to print out the name only once
Instead of an array, you could use a set, which can contain only distinct elements. You can use nameTracker.add(userName) and it will only add the name if it's not already in the set.
What you have will work just fine.
userName = "ThePlayersName" # constantly changing
nameTracker = []
def printUser(name):
if name not in nameTracker:
print(name)
printUser(userName)
nameTracker.append(userName)
printUser("Player 2")
nameTracker.append("Player 2")
printUser("Player 2")
prints
ThePlayersName
Player 2

How can I create a menu in python and use functions as my options?

I hope you're doing great! I would really appreciate if you help me with this problem of mine. I wrote this code that creates dictionary based on user's input, then updates it, sorts by keys and values, finds if the item is in the dictionary, counts the number of unique values and, finally, saves the original dictionary to the .txt file. The code itself works fine, but I wanted to present it as a menu so that user could choose what he/she would want to do next, but when I tried to just call the functions from the menu it didn't work and now I have no idea how to do it properly. Could you explain how I can do that? Thanks in advance!
1) Add a menu function, I only did the first three so that you can get the idea (you can do the rest of them), for example.
def menu():
print '1) Create a dictionary'
print '2) Update the dictionary'
print '3) Sort the dictionary'
task = raw_input('Enter the number to perform the corresponding task: ')
if task == '1':
user_dict = creating_dictionary()
elif task == '2':
try:
updating_dictionary(user_dict)
except UnboundLocalError:
print "A dictionary doesn't exist, you'll have to create one\n"
creating_dictionary()
elif task == '3':
try:
sorting_dictionary(user_dict)
except UnboundLocalError:
print "A dictionary doesn't exist, you'll have to create one\n"
creating_dictionary()
2) add menu() as your first statement in main()
3) at the end of every function add a call to menu()
4) If you set it up correctly then the only call you'll need in main() is menu(). You'll be able to delete all of the other function calls since at the end of every function you'll be calling menu().

Trying to call an function with a variable imbedded in the middle of it in Python

I'm creating a program with a menu that asks the user via raw_input to choose a specific chapter of narrative in the program they want to read. That portion of the code is:
mainma = raw_input ("Which chapter do you want? (1-10): ")
Here's where my problem is: I'm trying to code the call so that it will go to the requested chapter that is defined as:
Chap(mainma)menu()
as I was working on the assumption that if mainma = 1, it would invoke Chap1menu() where that particular chapter data is stored, the same if mainma = 3 it would invoke Chap3menu(). The syntax error I'm getting disagrees with me. What am I doing wrong?
You don't really want to try to turn user input directly into variable names; it's possible but it's messy, brittle, and insecure. What you want to do instead is create a list or dictionary that maps the input to the chapter functions; something like:
chapters = {'1': Chap1Menu,
'2': Chap2Menu,
#etc.
}
and then use it like so:
chapters[mainma]()
Just use m as a parameter to the function Chapmenu. For example:
def Chapmenu(m):
if m == 1:
# code for Chap1menu goes here
elif m == 2:
# code for Chap2menu goes here
elif m == 3:
# code for Chap3menu goes here
etc.
Then just call Chapmenu(mainma)
You have an opportunity for efficient code design here -- presumably the chapter menu functions share a lot of behavior between them. You shouldn't every copy-and-paste code in a program like that, because it's harder to read and a risk to update (too easy to get them out of whack with each other).
Whatever you were putting into Chapter#Menu, write a sliiiightly more general function that accepts the chapter number as an argument. This helps reuse code that's similar between chapters. The differences get stored in some list or dictionary (here insides, minimal):
insides = list('qwertywuiop')
def ChapterMenus(chapternum, **kwargs):
print('Chapter %d: About the Letter %s'%(chapternum, insides[chapternum]))
print(kwargs)
if __name__=='__main__':
mainma = raw_input("Which chapter do you want? (1-10): ")
mainma = int(mainma) #Be more helpful validating this
if mainma in range(1,11):
ChapterMenus(mainma, text='Ants')
else:
print('Tsk! A real chapter number, please!')

Python text adventure - how to create HINT and SAVE in every prompt

So, finally I'm getting to the end of LPTHW, and I'm creating my own text adventure type of game.
I want to incorporate a save function to the game (probably by using file write). Also, the game can give you hints based on your location in the game. What I basically need is following:
There will be lots of prompts for user input (raw_input) in while loops. I want to be able to type SAVE or HINT any time to trigger a function. How do I do this so I don't have to create the same conditional every time? (for example elif action == "HINT": print "...")
Is there a way to create some global expressions so that every time they're typed in the prompt, I can act on them? I will create a module with a dictionary that will reference a certain hint when the player is present in a certain location. I just want to avoid putting the same conditionals all over the place.
If you separate the input into a function, you can pass a hint and access save easily:
def user_input(prompt, hint):
while True:
ui = raw_input(prompt)
if ui.lower() == "hint":
print hint
elif ui.lower() == "save":
save()
else:
return ui
You could also add checking here that the user stays within specific choices (an additional argument), deal with any errors and only ever return valid input.
you should probably use a dictionary
def do_save(*args,**kwargs):
print "SAVE!"
def do_hint(*args,**kwargs):
print "HINT!"
def do_quit(*args,**kwargs):
print "OK EXIT!"
global_actions = {'SAVE':do_save,
'HINT':do_hint,
'QUIT':do_quit}
def go_north(*args,**kwargs):
print "You Go North"
def go_east(*args,**kwargs):
print "you go east"
def make_choice(prompt="ENTER COMMAND:",actions={},context_info={}):
choice = raw_input(prompt)
fn = actions.get(choice.upper(),lambda *a,**kw:sys.stdout.write("UNKOWN CHOICE!"))
return fn(some_context=context_info)
local_actions = {"NORTH":go_north,"EAST":go_east}
player_actions = dict(global_actions.items() + local_actions.items())
print "From Here You Can Go [North] or [East]"
result = make_choice(actions=player_actions,
context_info={"location":"narnia","player_level":5})
I don't know about the save feature but for hint you could just have;
If raw_input == hint:
print "whatever you want here"
Or if you need the hint to be different depending on your position you could have a variable for what the hint for that room is and have it update each time you enter a new room then have:
if raw_input == "hint":
print hintvariable
If this doesn't work then sorry, I'm new.

Return to code after function runs

I'm making a text-based game and need an application-wide command line that's able to be pulled up at any text entry. My plan was to have the commands contained within a module, and execute command(), which would then allow the user to enter a command (or get a list) that is then run (contained within the same module). This didn't work because I need a way to return to where the user was. Is there anyway to return to where the user was before they entered command mode, or is there a better way to do this?
This was my idea:
import commands
def something():
print "a question"
action = raw_input("> ")
if action == "command":
commands.commands()
elif "something else" in action:
do something
else:
error.error(1)
something()
Which then went to commands.py:
def commands():
print "Enter a command, help for a list, blah blah blah."
command = raw_input("$ ")
if command == "bag":
bag()
elif command == "other":
other()
def bag():
print "Action listing things in bag"
The problem is returning where the user left off.
What you need is a main game loop:
while game.is_running:
command = get_user_input()
user_do(command)
update_world()
This will repeat the three lines of code inside the while loop for as long as game.is_running is True. First, you get the user input. Next, you act on it. Finally, you perform any other updates your game needs, like moving or spawning monsters. At this point, it loops back and asks the user for another command.
Update: here is a working example:
# In commands.py:
def bag():
print 'bag'
def other():
print 'other'
def unrecognized():
print 'unknown command'
# In main.py:
import commands
def user_input():
print 'a question'
return raw_input('>')
def user_do(command):
# get the matching command out of commands, or pass back
# the unrecognized function if it's not found
action = getattr(commands, command, commands.unrecognized)
action()
is_running = True
while is_running:
command = user_input()
if command == 'quit':
is_running = False
else:
user_do(command)
In this example, I've cheated and am relying on the user input commands being identical to the name of the functions to be called. In user_do, the getattr call compares the string the user has input with the contents of the command module, returning the function of the same name if one exists, or the fallback function unrecognized if it doesn't. action will now either hold the command function or unrecognized.
If you don't want to have your user commands so tightly bound to the actual functions themselves, you can use a dict as a branching construct (or dispatch) instead of having a lot of if / elif / else statements:
# Modified main.py
import commands
COMMAND_DISPATCH = {
'bag': commands.bag,
'sack': commands.bag,
'other': commands.other,
# ...
}
# ...
def user_do(command):
action = COMMAND_DISPATCH.get(command, commands.unrecognized)
action()
In this example, rather than look up the functions in the commands module, we look them up in COMMAND_DISPATCH instead.
One more bit of advice: pretty soon you'll want to look at parsing the user input into more than just a single command. For this example, let's assume you want to be able to accept input of the form "command ... ". You can extend the user_input function to take care of this:
def user_input():
print 'a question'
user_input = raw_input('>').split(' ')
command = user_input[0]
arguments = user_input[1:]
return command, arguments
So if you enter 'foo bar baz', this would return the tuple ('foo', ['bar', 'baz']). Next we update the main loop to deal with the arguments.
while is_running:
# use tuple unpacking to split into command, argument pairs
command, arguments = user_input()
if command == 'quit':
is_running = False
else:
user_do(command, arguments)
Then make sure we pass them to the command:
def user_do(command, arguments):
action = COMMAND_DISPATCH.get(command, commands.unrecognized)
action(arguments)
And finally, we modify the commands to accept and handle the arguments:
def bag(arguments):
for argument in arguments:
print 'bagged ', argument
For a text adventure, you'll want a more substantial parser, something that deals with command object, command object preposition subject, and possibly even command adjective object ....
You should research "python finite state machine". It is pretty much exactly what you want.
Charming Python: Using state machines
Finite-state machine
wiki.python.org/moin/FiniteStateMachine
What is a state machine?
An overly accurate description of a state machine is that it is a
directed graph, consisting of a set of nodes and a corresponding set
of transition functions. The machine "runs" by responding to a series
of events. Each event is in the domain of the transition function
belonging to the "current" node, where the function's range is a
subset of the nodes. The function returns the "next" (perhaps the
same) node. At least one of these nodes must be an end-state. When an
end-state is reached, the machine stops.
When to use a state machine ...
Start in an initial state.
Read a line of input.
Depending on the input and the current state, either transition to a new state or process the line as appropriate for the current state.
Similar to what #MatthewTrevor suggested in his answer, you would have a main loop, and pass a "state" context to the first entry point call (start or intro or whatever). That call can change the state context to point at something else. When control reaches back to the main loop again and it checks the state, it will run the new state.

Categories