I made a dictionary in IDE and made a function to take input from user and it takes the input but when I rerun that program and try to print the output It don`t show anything.
Here is the code, help if anyone want to.
# Created dictionary.
list = {}
# Made a Function to save data.
def up():
v = int(input(f"How many inputs you want to give : "))
for i in range(v):
a = input(f"Give words you want to put : ")
b = input(f"Assign : ")
list.update({a:b})
print(f"Saved",{a:b})
value = input(f"What you want to do ? \nSee List or update it. \nIf you want to update type 'u' , If you want to see list type 's' ")
if value == "s":
print(list)
elif value == "u":
up()
Information in your variables is stored during the execution of your script. It is not automatically carried across to different executions of your script. Each one is a blank slate. Even if it weren't, the first line of your program sets list to an empty dictionary.
At the moment, you're putting salt on your broccoli, eating it, then expecting the broccoli you eat tomorrow to also have salt on it.
You could serialise the dictionary to a file, that can be read back in on next execution, rather than starting with an empty dictionary each time.
Related
I've been trying to create a program which allows users to view a text file's contents and delete some or all of a single entry block.
An example of the text's file contents can be seen below:
Special Type A Sunflower
2016-10-12 18:10:40
Asteraceae
Ingredient in Sunflower Oil
Brought to North America by Europeans
Requires fertile and moist soil
Full sun
Pine Tree
2018-12-15 13:30:45
Pinaceae
Evergreen
Tall and long-lived
Temperate climate
Tropical Sealion
2019-01-20 12:10:05
Otariidae
Found in zoos
Likes fish
Likes balls
Likes zookeepers
Big Honey Badger
2015-06-06 10:10:25
Mustelidae
Eats anything
King of the desert
As such, the entry block refers to all lines without a horizontal space.
Currently, my progress is at:
import time
import os
global o
global dataset
global database
from datetime import datetime
MyFilePath = os.getcwd()
ActualFile = "creatures.txt"
FinalFilePath = os.path.join(MyFilePath, ActualFile)
def get_dataset():
database = []
shown_info = []
with open(FinalFilePath, "r") as textfile:
sections = textfile.read().split("\n\n")
for section in sections:
lines = section.split("\n")
database.append({
"Name": lines[0],
"Date": lines[1],
"Information": lines[2:]
})
return database
def delete_creature():
dataset = get_dataset()
delete_question = str(input("Would you like to 1) delete a creature or 2) only some of its information from the dataset or 3) return to main page? Enter 1, 2 or 3: "))
if delete_question == "1":
delete_answer = str(input("Enter the name of the creature: "))
for line in textfile:
if delete_answer in line:
line.clear()
elif delete_question == "2":
delete_answer = str(input("Enter the relevant information of the creature: "))
for line in textfile:
if delete_answer in line:
line.clear()
elif delete_question == "3":
break
else:
raise ValueError
except ValueError:
print("\nPlease try again! Your entry is invalid!")
while True:
try:
option = str(input("\nGood day, This is a program to save and view creature details.\n" +
"1) View all creatures.\n" +
"2) Delete a creature.\n" +
"3) Close the program.\n" +
"Please select from the above options: "))
if option == "1":
view_all()
elif option == "2":
delete()
elif option == "3":
break
else:
print("\nPlease input one of the options 1, 2 or 3.")
except:
break
The delete_function() is meant to delete the creature by:
Name, which deletes the entire text block associated with the name
Information, which deletes only the line of information
I can't seem to get the delete_creature() function to work, however, and I am unsure of how to get it to work.
Does anyone know how to get it to work?
Many thanks!
Your problem with removing lines from a section is that you specifically hardcoded which line represents what. Removing a section in your case will be easy, removing a line will, if you do not change your concept, involve setting the line in question to empty or to some character representing the empty string later.
Another question here is, do you need your sections to remain ordered as they were entered, or you can have them sorted back in a file in some other order.
What I would do is to change the input file format to e.g. INI file format. Then you can use the configparser module to parse and edit them in an easy manner.
The INI file would look like:
[plant1]
name="Some plant's English name"
species="The plant's Latin species part"
subspecies="The plant's subspecies in Latin ofcourse"
genus="etc."
[animal1]
# Same as above for the animal
# etc. etc. etc.
configparser.ConfigParser() will let you load it in an dictionarish manner and edit sections and values. Sections you can name animal1, plant1, or use them as something else, but I prefer to keep the name inside the value, usually under the name key, then use configparser to create a normal dictionary from names, where its value is another dictionary containing key-value pairs as specified in the section. And I reverse the process when saving the results. Either manually, or using configparser again.
The other format you might consider is JSON, using the json module.
Using its function dumps() with separators and indentation set correctly, you will get pretty human-readable and editable output format. The nice thing is that you save the data structure you are working with, e.g. dictionary, then you load it and it comes back as you saved it, and you do not need to perform some additional stuff to get it done, as with configparser. The thing is, that an INI file is a bit less confusing for an user not custom to JSON to construct, and results in less errors, while JSON must be strictly formatted, and any errors in opening and closing the scopes or with separators results in whole thing not working or incorrect input. And it easily happens when the file is big.
Both formats allows users to put empty lines wherever they want and they will not change the way the file will be loaded, while your method is strict in regard to empty lines.
If you are expecting your database to be edited only by your program, then use the pickle module to do it and save yourself the mess.
Otherwise you can:
def getdata (stringfromfile):
end = {}
l = [] # lines in a section
for x in stringfromfile.strip().splitlines():
x = x.strip()
if not x: # New section encountered
end[l[0].lower()] = l[1:]
l = []
continue
end.append(x)
end[l[0].lower()] = l[1:] # Add last section
# Connect keys to numbers in the same dict(), so that users can choose by number too
for n, key in enumerate(sorted(end)):
end[n] = key
return end
# You define some constants for which line is what in a dict():
values = {"species": 0, "subspecies": 1, "genus": 2}
# You load the file and parse the data
data = getdata(f.read())
def edit (name_or_number, edit_what, new_value):
if isinstance(name_or_number, int):
key = data[name_or_number]
else:
key = name_or_number.lower().strip()
if isinstance(edit_what, str):
edit_what = values[edit_what.strip().lower()]
data[key][edit_what] = new_value.strip()
def add (name, list_of_lines):
n = len(data)/2 # Number for new entry for numeric getting
name = name.strip().lower()
data[name] = list_of_lines
data[n] = name
def remove (name):
name = name.lower().strip()
del data[name]
# Well, this part is bad and clumsy
# It would make more sense to keep numeric mappings in separate list
# which will do this automatically, especially if the database file is big-big-big...
# But I started this way, so, keeping it simple and stupid, just remap everything after removing the item (inefficient as hell itself)
for x in data.keys():
if isinstance(x, int):
del data[x]
for n, key in enumerate(sorted(data)):
data[n] = key
def getstring (d):
# Serialize for saving
end = []
for l0, ls in d.items():
if isinstance(l0, int):
continue # Skip numeric mappings
lines = l0+"\n"+"\n".join(ls)
end.append(lines)
return "\n\n".join(end)
I didn't test the code. There might be bugs.
If you need no specific lines, you can modify my code easily to search in the lines using the list.index() method, or just use numbers for the lines if they exist when you need to get to them. For doing so with configparser, use generic keys in a section like: answer0, answer1..., or just 0, 1, 2..., Then ignore them and load answers as a list or however. If you are going to use configparser to work on the file, you will get sometimes answer0, answer3... when you remove.
And a warning. If you want to keep the order in which input file gives the creatures, use ordereddict instead of the normal dictionary.
Also, editing the opened file in place is, of course, possible, but complicated and inadvisable, so just don't. Load and save back. There are very rare situations when you want to change the file directly. And for that you would use the mmap module. Just don't!
My question is about getting a user to pull and item from a list. If the item from the list isn't pulled from the list I want to tell the user that he is incorrect. So my code looks like this:
Body_Type = ['Large', 'Medium', 'Small']
print('Create a Character-')
print('Body Type Choices: ' + str(Body_Type))
bt = input('Enter your Body Type: ')
while bt != Body_Type:
if bt == Body_Type[0:]:
print('Your Body Type is: ' + bt)
else:
print('Invalid Body Type')
What I'm trying to do is make my user create a character. This is just the first part of my first simple project. I want to have him pull from one of the items on the list, being "Large, Medium, Small" respectively. I want it to repeat until the user chooses one of the three. I tried to use or but it seems to feel unorganized and I'd have to break up the list and assign each individual variable.
Thanks in advance!
Several errors here like comparing a string to a list, or random slicing hoping that it would work. And the fact that your input statement is before the loop creates an infinite loop because you're comparing 2 variables of a different type again and again (bt != Body_Type is always True regardless of the content of bt since left hand is a string, right hand is a list).
But it shouldn't be so complex to write some working code.
I would create an infinite loop and break only if choice is in the list:
while True:
bt = input('Enter your Body Type: ')
if bt in Body_Type:
print('Your Body Type is: ' + bt)
break
else:
print('Invalid Body Type')
simpler and clearer (and repeats input if fails). The infinite loop (with an always true condition) allows to avoid double input call & test. Just loop, input the string, and break from the loop if matches.
The key statement you were looking for was bt in Body_Type which tests if the string is within the list.
I'm very new at coding, and I'm trying to create a shop list with items and prices on it.
That is, once typed in all the items, the function should calculate the sum and stop the moment you exceed the budget.
So I wrote something like:
def shoplist():
list={"apple":30, "orange":20, "milk":60......}
buy=str(input("What do you want to purchase?")
If buy in list:
While sum<=budget:
sum=sum+??
shoplist ()
I really don't know how to match the input of an item with the price in the list...
My first thought is to use 'if', but it's kinda impractical when you have more than 10 items on the list and random inputs.
I'm in desperate need of help....So any suggestions would be nice!! (or if you have a better solution and think me writing it this way is complete garbage... PLEASE let me know what those better solutions areðŸ˜ðŸ˜ðŸ˜
The code you post will not run in python. list is a builtin and should not be used for a variable name, and is doubly confusing since it refers to a dict object here. input() already returns a str so the cast has no effect. if and while should be lowercase, and there is no indentation, so we have no way of knowing the limits of those statements.
There are so many things wrong, take a look at this:
def shoplist(budget):
prices = {"apple":30, "orange":20, "milk":60}
# Initialise sum
sum = 0
while sum <= budget:
buy = input("What do you want to purchase?")
# Break out of the loop if the user hts <RETURN>
if not buy: break
if buy in prices:
sum += prices[buy] # This gets the price
else:
print("Invalid item", buy)
shoplist(142)
So what have I changed? The budget has to come from somewhere, so I pass it in as a parameter (142, I made that up). I initialise the sum to zero, and I moved the while loop to the outside.
Notice as well lots of whitespace - it makes the code easier to read and has no effect on performance.
Lots of improvements to make. The user should be shown a list of possible items and prices and also how much budget there is left for each purchase. Note as well that it is possible to go over budget since we might only have 30 in the budget but we can still buy milk (which is 60) - we need another check (if statement) in there!
I'll leave the improvements to you. Have fun!
Take a look at this as an example:
# this is a dictionary not a list
# be careful not using python reserved names as variable names
groceries = {
"apple":30,
"orange":20,
"milk":60
}
expenses = 0
budget = 100
cart = []
# while statements, as well as if statements are in lower letter
while expenses < budget:
# input always returns str, no need to cast
user_input = input("What do you want to purchase?")
if user_input not in groceries.keys():
print(f'{user_input} is not available!')
continue
if groceries[user_input] > budget - expenses:
print('You do not have enough budget to buy this')
user_input = input("Are you done shopping?Type 'y' if you are.")
if user_input == 'y':
break
continue
cart.append(user_input)
# this is how you add a number to anotherone
expenses += groceries[user_input]
print("Shopping cart full. You bought {} items and have {} left in your budget.".format(len(cart), budget-expenses))
I've made some changes to your code to make it work, with explanation including using comments indicated by the # symbol.
The two most important things are that all parentheses need to be closed:
fun((x, y) # broken
fun((x, y)) # not broken
and keywords in Python are all lowercase:
if, while, for, not # will work
If, While, For, Not # won't work
You might be confused by True and False, which probably should be lowercase. They've been that way so long that it's too late to change them now.
budget = 100 # You need to initialize variables before using them.
def shoplist():
prices = { # I re-named the price list from list to prices
'apple' : 30, # because list is a reserved keyword. You should only
'orange' : 20, # use the list keyword to initialize list objects.
'milk' : 60, # This type of object is called a dictionary.
} # The dots .... would have caused an error.
# In most programming languages, you need to close all braces ().
# I've renamed buy to item to make it clearer what that variable represents.
item = input('What do you want to purchase? ')
# Also, you don't need to cast the value of input to str;
# it's already a str.
if item in prices:
# If you need an int, you do have to cast from string to int.
count = int(input('How many? '))
cost = count*prices[item] # Access dictionary items using [].
if cost > budget:
print('You can\'t afford that many!')
else:
# You can put data into strings using the % symbol like so:
print('That\'ll be %i.' % cost) # Here %i indicates an int.
else:
print('We don\'t have %s in stock.' % item) # Here %s means str.
shoplist()
A lot of beginners post broken code on StackOverflow without saying that they're getting errors or what those errors are. It's always helpful to post the error messages. Let me know if you have more questions.
One part of my program allows the user to check whether the clues they have entered are correct with the solved version which is in an external file named solved.txt... So far I have the code shown below however it is only showing the three clue pairings at the beginning of the program which are correct, not the ones which I have added throughout the program. I think this is just something minor but I am a bit stuck on what to change.
Here is my code so far...
def check_clues():
# Dictionary to hold all of the symbol/letter combos
coded_dict = {}
# Go through each symbol/letter combination together
with open("words.txt") as fw, open("solved.txt") as fs:
for fw_line, fs_line in zip(fw, fs):
for fw_symbol, fs_letter in zip(fw_line.strip(), fs_line.strip()):
# Add the symbol/letter combination to the dictionary
coded_dict[fw_symbol] = fs_letter
correct_clues = []
with open("clues.txt") as fc:
for fc_line in fc:
# If the symbol is in the dictionary and the letter matches the symbol
if fc_line[1] in coded_dict and coded_dict[fc_line[1]] == fc_line[0]:
# Add a correct clue to your list
correct_clues.append(fc_line.strip())
print("You got a total of {0} correct: {1}".format(len(correct_clues), ", ".join(correct_clues)))
if __name__ == "__main__":
check_clues()
Below is a link to what is in each of the files...
http://www.codeshare.io/vgwrC
If needed, I will add the code for all of my program...
Pretty new to python/programming in general, this is my biggest project yet.
I am writing a program that will do SUVAT equations for you. (SUVAT equations are used to find the displacement, start/end velocity, acceleration and time travelled by an object with constant velocity, you may call them something different.)
I made this list:
variables = ["Displacement", "Start Velocity", "End Velocity", "Acceleration", "Time"]
which is used in the following while/for loop:
a = 0
while a==0:
for variable in variables:
# choice1 is what the user is looking to calculate
choice1 = raw_input("Welcome to Mattin's SVUVAT Simulator! Choose the value you are trying to find. You can pick from " + str(variables))
# will execute the following code when the for loop reaches an item that matches the raw_input
if choice1 == variable:
print "You chave chosen", choice1
variables.remove(variable) #Removes the chosen variable from the list, so the new list can be used later on
a = 1 # Ends the for loop by making the while loop false
# This part is so that the error message will not show when the raw_input does not match with the 4 items in the list the user has not chosen
else:
if choice1 == "Displacement":
pass
elif choice1 == "Start Velocity":
pass
elif choice1 == "End Velocity":
pass
elif choice1 == "Acceleration":
pass
# This error message will show if the input did not match any item in the list
else:
print "Sorry, I didn't understand that, try again. Make sure your spelling is correct (Case Sensitive), and that you did not inlcude the quotation marks."
Hopefully the comments I have written in the code should explain my intentions, if not, feel free to ask anything.
The problem is that when I run the code, and input choice1, the for loop activates the last line of code:
else:
print "Sorry, I didn't understand that, try again. Make sure your spelling is correct (Case Sensitive), and that you did not inlcude the quotation marks."
and then prompts me to enter the input again, and will do this as many times as it needs to get to the item on the list that I am typing.
However, I specifically coded that if what I input does not match the item on the list the for loop is currently checking, but does match one of the other items on the list, then it should pass and loop round to checking the next item.
I am probably doing something stupid, but I don't see it, so please help me figure out what I have to do to get my desired result? I assumed it was the syntax I had wrong so that is why that is the title.
Thanks for any help, I appreciate it.
Besides the problem with the indentation in your pasted code, I would rewrite it as such:
while True:
choice = raw_input('...')
if choice in variables:
print "You chave chosen", choice
# Remove the chosen member from the list
variables = [v for v in variables if v != choice]
# Break out of loop
break
# Print error messages etc.
Also remember that string comparisons are case sensitive. I.e 'Displacement' != 'displacement'.