Combine/ "concatenate" two variables, one being a user input - python

I am looking to combine a user inputted string as one variable (it is dynamic, of course) and use it to make another variable.
Example:
x = str(input("What do you want to buy? "))
(I want the new variable to be like x_cost - but of course you don't actually write that)
Let's say that the user inputs apple, so the new variable would be: apple_cost.
Is there a way to do this?

You should use a dict for this. I get that it can be hard to understand what a dict is if you've never seen it before, but if you want to learn, it's absolutely necessary to slow down and understand these things.
costs = {}
item_name = input("What do you want to buy? ")
costs[item_name] = input('Price? ')
So you can try and enter a few things
costs = {}
for i in range(4):
item_name = input("What do you want to buy? ")
costs[item_name] = input('Price? ')
How would you print out all these new variables if you don't know the names? With a dict it is easy:
for key, value in costs.items():
print(key, "costs", value)

A good way of solving this problem would be to use a dictionary. A dictionary "entry" holds two objects, a key and an item. You can think of the key as the magic word and the item as the genie--by calling the key (i.e. saying the magic words) you can reference an item (i.e. summoning the genie).
Let's go with the fruit example. If you want the user to input one of three fruits (lets say apple, pear, and cantaloupe) and have it correspond to a price. If we say the apple costs one dollar, the pear two, and the cantaloupe one hundred, then here is what our dictionary would look like:
#This is our dictionary. you can see the keyword (the fruit) goes first
#in order to summon the price, which we will store in another variable
fruit_dict = {'apple': 1.00, 'pear': 2.00, `cantaloupe`: 100.00}
Now that we have a working dictionary, let us write a program!
#First we define the dictionary
fruit_dict = {"apple": 1.00, "pear": 2.00, "cantaloupe": 100.00}
#Now we need to ask for user input
fruit = raw_input("What fruit would ya like?\n>>> ")
#Next, we look for the fruit in our dictionary. We will use a function
#called `values()`, which returns `True` or `False`.
if fruit in fruit_dict:
fruit_cost = fruit_dict[fruit] #accessing the value with dictname[key]
Easy as that! Now you can do what you want with the variable.
Best of luck, and happy coding!

You cannot create variable names dynamically.
What you need is a dictionary.
There are two ways to achieve what you want
mydict = {}
x = str(input("What do you want to buy? "))
mydict[str(x)+'_cost'] = 'some value'
Now using user input directly to populate a dictionary can be a risky business from security point of view, so you may want do:
import hashlib
mydict = {}
x = str(input("What do you want to buy? "))
hashkey = hashlib.md5(str(x)).hexdigest()
mydict[hashkey+'_cost'] = 'some value'

In python everything is object. A program starts in a main module main. Each module, class, etc has its own namespace (a dictionary) where variables are defined. So if you put a key in that namespace dict then it becomes variable. You can make use of that variable to point to any other object you want.
Just look at this code...
try this in python interactive mode....
import sys
sys.modules['__main__'].__dict__ # this is your main modules namespace.
So just push the name of variable into the dict as key and assign the value/object.
sys.modules['__main__'].__dict__['apple_cost']]
apple_cost = 10.5
You can access the namespace of any containers class/modules/etc... But I would not suggest you to do what I explained (this is just one way of doing it. little bit hacky/ugly) instead use descriptors or simple getattr method in a class (bit advanced but something useful to learn) to implement some thing like this.

Related

Case insensitive Full Name dictionary search

I am creating a dictionary with "Full Name": "Birthday" for numerous people as an exercise.
The program should ask
"Who's birthday do you want to look up?"
I will input a name, say "Benjamin Franklin"
And it will return his birthday: 1706/01/17.
Alright, the problem I am encountering is name capitalization.
How can I input "benjamin franklin" and still find "Benjamin Franklin" in my dictionary? I am familiar with .lower() and .upper() functions, however I am not able to implement them correctly, is that the right way to approach this problem?
Here is what I have
bday_dict = {"Person1": "YYYY/MM/DD1",
"Person2": "YYYY/MM/DD2",
"Benjamin Franklin": "1706/01/17"}
def get_name(dict_name):
name = input("Who's birthday do you want to look up? > ")
return name
def find_bday(name):
print(bday_dict[name])
find_bday(get_name(bday_dict))
The best way to do this is to keep the keys in your dictionary lowercase. If you can't do that for whatever reason, have a dictionary from lowercase to the real key, and then keep the original dictionary.
Otherwise, Kraigolas's solution works well, but it is O(N) whereas hashmaps are supposed to be constant-time, and thus for really large dictionaries the other answer will not scale.
So, when you are setting your keys, do bday_dict[name.lower()] = value and then you can query by bday_dict[input.lower()].
Alternatively:
bday_dict = {"John": 1}
name_dict = {"john": "John"}
def access(x):
return bday_dict[name_dict[x.lower()]]
Probably the most straight forward way I can think of to solve this is the following:
def get_birthday(name):
global bday_dict
for person, bday in bday_dict.items():
if name.lower() == person.lower():
return bday
return "This person is not in bday_dict"
Here, you just iterate through the entire dictionary using the person's name paired with their birthday, and if we don't find them, just return a message saying we don't have their birthday.
If you know that all names will capitalize the first letter of each word, you can just use:
name = ' '.join([word.capitalize() for word in name.split()])
then you can just search for that. This is not always the case. For example, for "Leonardo da Vinci" this will not work, so the original answer is probably the most reliable way to do this.
One final way to do this would be to just store the names as lowercase from the beginning in your dictionary, but this might not be practical when you want to draw a name from the dictionary as well.
Depending what your exercise allows, I would put the names in the dictionary as all lowercase or uppercase. So:
bday_dict = {"person1": "YYYY/MM/DD1",
"person2": "YYYY/MM/DD2",
"benjamin franklin": "1706/01/17"}
And then look up the entered name in the dictionary like this:
def find_bday(name):
print(bday_dict[name.lower()])
You may also want to do a check that the name is in the dictionary beforehand to avoid an error:
def find_bday(name):
bday = bday_dict.get(name.lower(), None)
if bday:
print(bday)
else:
print("No result for {}.".format(name))

Using user input to select a variable to modify?

I am trying to modify a variable based on user input. For example if the user wanted to change their strength variable they would type in "strength" and then that variable (tied to a player object so in this example player.strength) would be reassigned the new value.
I have attempted using dictionaries to hold the variable name as this is what I've used to call functions/methods as well but after browsing here a bit have realized this will not work due to it being immutable.
My current attempt looks like this:
skill_dict = {"Swords": self.swords}
answer = input("Which skill would you like to be proficient in?")
skill_dict[answer] += 10
print(skill_dict[answer])
print(self.swords)
The output however shows that this not work with the dictionary value being changed to 10 while the actual variable value remaining unchanged.
Is there a way to do this?
Use a dict to contain all the player's stats, like this:
class Player:
def __init__(self, swords, strength):
self.skills = {'swords': swords, 'strength': strength}
def become_proficient(self):
answer = input("Which skill would you like to be proficient in? ")
self.skills[answer] += 10
print(self.skills[answer])
Example run:
>>> player = Player(5, 6)
>>> player.become_proficient()
Which skill would you like to be proficient in? swords
15
>>> player.become_proficient()
Which skill would you like to be proficient in? strength
16
>>> player.skills
{'swords': 15, 'strength': 16}
On the other hand, if you need to use attributes, you can use setattr() and getattr(), but this allows the user access to any attributes, which is generally a bad idea.
answer = input("Which skill would you like to be proficient in? ")
setattr(self, answer) = getattr(self, answer) + 10

Nested for loops iterating over multiple dictionaries, is there an easier way?

So my lazy rear is trying to create a meal plan generator in python 3.x so I don't have to spend 30min every Friday figuring out what I should eat, but I'm new to coding and struggling with something. I'm still going through the Udemy course, but I wanted to get my fingers dirty with code to properly learn. Anywho, here's what I've got so far:
class Meals():
def __init__(self,breakfast,lunch,dinner):
self.breakfast=breakfast
self.lunch=lunch
self.dinner=dinner
def __str__(self):
return f"Breakfast will be {self.breakfast}.\nLunch will be {self.lunch}.\nDinner will be {self.dinner}."
def cost(self):
day_meals=[self.breakfast,self.lunch,self.dinner]
day_cost=0
for i in day_meals:
for ingredient in i:
for key,value in Shop2.items():
if key in ingredient:
day_cost+=value
return f"Today will cost £{round(day_cost,2)}."
If I do:
monday_meals=Meals(random.choice(list(breakfasts.keys())),random.choice(list(lunches.keys())),random.choice(list(dinners.keys())))
And then call monday_meals.breakfast, then I get the result I want, the randomly chosen key from the 'breakfast' dictionary, but whenever I call for:
monday_meals.cost()
then I get £0 with no errors showing.
For reference, my testing dictionaries are as follows:
breakfasts={"a bowl of Rice Crispies":["cereal_1","milk"],"Weetabix":["cereal_2","milk"],"some Golden Grahams":["cereal_3","milk"],"toast":["bread","butter"],"scrambled eggs":["egg","egg","milk"]}
lunches={"cereal bars":["cereal_bar","cereal_bar"],"a boring ham sandwich":["bread","ham"],"some fruit":["banana","apple"],"salad":"salad_bag"}
dinners={"Student Meal #1":["mince","red_sauce","pepper","onion"],"Student Meal #2":["c_breast","white_sauce","onion","pepper"],"Student Meal #3":["egg","pepper","tomato","onion"]}
Shop2={"egg":0.3,"tomato":0.35,"pepper":0.33,"onion":0.4,"mince":1.2,"c_breast":0.7,"rice":0.8,"red_sauce":1.4,"white_sauce":1.5,"cereal_1":0.4,"milk":0.13,"cereal_2":0.35,"cereal_3":0.45,"bread":0.04,"butter":0.04,"cereal_bar":0.75,"ham":0.25,"banana":0.3,"apple":0.3,"salad":0.75}
I'd really appreciate any help with finding an easier way to calculate the cost of a day's meals.
You can implement your design with:
# inside your class:
#staticmethod
def calculate_meal_cost(ingredients, shopdict):
return sum(shopdict[ingredient] for ingredient in ingredients)
#property
def cost(self):
breakfast_cost = self.calculate_meal_cost(breakfasts[self.breakfast], Shop2)
lunch_cost = self.calculate_meal_cost(lunches[self.lunch], Shop2)
dinner_cost = self.calculate_meal_cost(dinners[self.dinner], Shop2)
return breakfast_cost + lunch_cost + dinner_cost
Then:
meal = Meal(...) # however you pick your meals is fine
meal.cost # note: no parens
The problem is in what you pass in when you instantiate the class. breakfasts.keys() just gives you the keys of the dict, as the name implies: the keys are the things to the left of the colon, eg "a bowl of Rice Crispies". The actual ingredients are the values, but these never get sent to the Meals instance; so when you iterate through the "ingredients" you're actually iterating through the letters of the key.
You could fix this by using .values() instead of .keys() there, although a nicer way might be to pass both key and value so that your __str__ method outputs the description, not the ingredients; I'll leave that as an exercise...
Your Meals object is being initialized with the String name of the meal (e.g. random choice of breakfasts.keys() might be "Weetabix").
When you iterate through day_meals and do "ingredient in i", you are actually iterating through each "character" of Weetabix, so your ingredients would be "W" "e" "e" .. and so on.
Instead, you may want to initialize Meals with a choice of breakfasts.items(). Then you would have a tuple, e.g. ("Weetabix",["cereal_2","milk"]), in self.breakfast.
You can then unpack this in your loop:
for name,ingredients in day_meals:
for i in ingredients:
# and so on..
After you create Meals object, you have to call cost method. For now you only create object. Try:
monday_meals=Meals(random.choice(list(breakfasts.keys())),random.choice(list(lunches.keys())),random.choice(list(dinners.keys())))
print monday_meals.cost()
print monday_meals

How do I define a function in python to choose a list.

I am trying to define a function to choose a list. I am writing a text adventure. I chose to represent the rooms as lists, with descriptions, monsters and so on.
Now I want to define a function get_room(id) to bring me the right room
Room1=[description1,monster1]
Room2=[description2,monster2]
I guess I could try to make a list of the lists and pick out the right room from that. But wouldn't that be slower?
I am new to programming so I would prefer if the solution doesn't involve classes if at all possible. I am using python 2.7.2.
You can make use of dictionary like this:
dict = {
'Room1' : ['description1','monster1'],
'Room2' : ['description2','monster2']
}
And than call them like:
print dict['Room1']
In my opinion you may declare your rooms in a unique variable:
valid_rooms = [['description1', 'monster1'],
['description2', 'monster2']]
So that it becomes easier for manipulating them.
Example for getting the user required position room:
var = raw_input("Please enter room number: ")
print("you entered"), var
selectedRoom = int(var)
print( "room index %d : %s" % (selectedRoom, valid_rooms[selectedRoom]))
Important: I strongly recommend you to test the int conversion of user input:
try:
myint = int(var)
except ValueError:
print("Sorry you do not enter a valid INTEGER!")
Remark: in the proposed scenario the function get_room() would be very simple (maybe not so useful)
def get_room(id):
return valid_rooms[id]
Note that in python 3.x raw_input was rename input.
If your room id is an integer you should use a list.
rooms = [Room1, Room2]
# I assume you want to assign your rooms a number from 1 to ...
def get_room(id):
return rooms[id - 1]
If your room is is not an integer but, for example, a string you should use a dictionary.
rooms = {
"room1": Room1,
"room2": Room2
}
def get_room(id):
return rooms[id]
In both cases, whenever you are using dictionary or list you should assume that access to the element is very fast. It is constant time which means that whenever dictionary/list has 10, 100, or 100000 elements selecting element from them will take the same amount of time.

Python references to references in python

I have a function that takes given initial conditions for a set of variables and puts the result into another global variable. For example, let's say two of these variables is x and y. Note that x and y must be global variables (because it is too messy/inconvenient to be passing large amounts of references between many functions).
x = 1
y = 2
def myFunction():
global x,y,solution
print(x)
< some code that evaluates using a while loop >
solution = <the result from many iterations of the while loop>
I want to see how the result changes given a change in the initial condition of x and y (and other variables). For flexibility and scalability, I want to do something like this:
varSet = {'genericName0':x, 'genericName1':y} # Dict contains all variables that I wish to alter initial conditions for
R = list(range(10))
for r in R:
varSet['genericName0'] = r #This doesn't work the way I want...
myFunction()
Such that the 'print' line in 'myFunction' outputs the values 0,1,2,...,9 on successive calls.
So basically I'm asking how do you map a key to a value, where the value isn't a standard data type (like an int) but is instead a reference to another value? And having done that, how do you reference that value?
If it's not possible to do it the way I intend: What is the best way to change the value of any given variable by changing the name (of the variable that you wish to set) only?
I'm using Python 3.4, so would prefer a solution that works for Python 3.
EDIT: Fixed up minor syntax problems.
EDIT2: I think maybe a clearer way to ask my question is this:
Consider that you have two dictionaries, one which contains round objects and the other contains fruit. Members of one dictionary can also belong to the other (apples are fruit and round). Now consider that you have the key 'apple' in both dictionaries, and the value refers to the number of apples. When updating the number of apples in one set, you want this number to also transfer to the round objects dictionary, under the key 'apple' without manually updating the dictionary yourself. What's the most pythonic way to handle this?
Instead of making x and y global variables with a separate dictionary to refer to them, make the dictionary directly contain "x" and "y" as keys.
varSet = {'x': 1, 'y': 2}
Then, in your code, whenever you want to refer to these parameters, use varSet['x'] and varSet['y']. When you want to update them use varSet['x'] = newValue and so on. This way the dictionary will always be "up to date" and you don't need to store references to anything.
we are going to take an example of fruits as given in your 2nd edit:
def set_round_val(fruit_dict,round_dict):
fruit_set = set(fruit_dict)
round_set = set(round_dict)
common_set = fruit_set.intersection(round_set) # get common key
for key in common_set:
round_dict[key] = fruit_dict[key] # set modified value in round_dict
return round_dict
fruit_dict = {'apple':34,'orange':30,'mango':20}
round_dict = {'bamboo':10,'apple':34,'orange':20} # values can even be same as fruit_dict
for r in range(1,10):
fruit_set['apple'] = r
round_dict = set_round_val(fruit_dict,round_dict)
print round_dict
Hope this helps.
From what I've gathered from the responses from #BrenBarn and #ebarr, this is the best way to go about the problem (and directly answer EDIT2).
Create a class which encapsulates the common variable:
class Count:
__init__(self,value):
self.value = value
Create the instance of that class:
import Count
no_of_apples = Count.Count(1)
no_of_tennis_balls = Count.Count(5)
no_of_bananas = Count.Count(7)
Create dictionaries with the common variable in both of them:
round = {'tennis_ball':no_of_tennis_balls,'apple':no_of_apples}
fruit = {'banana':no_of_bananas,'apple':no_of_apples}
print(round['apple'].value) #prints 1
fruit['apple'].value = 2
print(round['apple'].value) #prints 2

Categories