Print variable by input - python

How to print variable name by input, Example:
a = 1
b = 2
what_variable = input('Which Variable?: ') #User for example introduces 'b'
Console: 2

You can write
print(globals()[what_variable])
but it's not a good approach. Use a dict instead

You can use exec:
var = input('Which Variable?: ')
exec("print(" + var + ")")
Output:
Which Variable?: b
2
>>

Just do the following:
print(eval(input('Which Variable?: ')))
You can also do
print(globals()[input('Which Variable?: ')])

While the other answers seem to address the obvious solution, it's not very 'Pythonic'. The main issues with these is, by far, safety. Let's say that your user inputs apiKey, and you happen to have a variable by that name... let's just say your bank statement is probably looking at a slight increase in magnitude. What most people in these answers don't realise is that using .globals()[input()] is no safer than eval(input()), because, shockingly, people store private info in variables. Alternatively, if it points to a method, e.g
a = print
b = os.system
eval(input())()
I could enter any function name there, and the damage would be done before the second () executes.
Why? Well, let's take a look at how exec and eval work (I won't go into the difference here, see this question for that). All they do is evaluate the string as Python code, and (simplifying here) return the value of the evaluation:
var1 = 3
print(eval("var1"))
# ====is equal to====
var1 = 3
print(var1)
(where var1 as a string obviously comes from the input typed in)
But if someone enters something malicious, this is essentially the basis of an SQL injection:
(where userInput is substituted by a user's input into an input())
userInput = "a + os.system('reboot now')"
print(eval(userInput))
# ====is equal to====
print(a + os.system('shutdown now')
and you suddenly find your computer's off.
Therefore, we'd either use a:
Dictionary (or object): x={a:1, b:2}, then do x[input()]
Array x=[1, 2], then do x[["a", "b"].index(input())]
Simply don't. Find a way to work around it. What's wrong with an if/else set? It's not good practise, because of the safety concerns outlined above. What most people seem to miss about dictionaries (or my array option) is that if you enter a malformed input (i.e not a or b), it would result in either uncaught errors being thrown, or undefineds being thrown around. And if you're going to do input validation, you're using an if statement anyway, so why not do it from the onset?

Related

(python) Let a string be recognised as a already defined variable

x= 1
a_1_add = "message 1"
a_2_add = "message 2"
while x<3:
y = "a_" + x + "_add"
print(y)
x += 1
How do I get python to get make it print "message 1', "message 2" instead of "a_1_add"?
I want to specifically make the string in y to be recognised as a variable. How to I do that?
I want to have a code that automatically change from the variable "a_1_add" to "a_2_add" and so on but don't want to manually write it out since the difference is only the number in the middle.
Edit: I know of "for loop" (a thank you to those that suggested it) but for my code (not so simple as the example I wrote out) I really need to use the while loop.
Thanks in advance. I am a beginner in python. Really appreciate your help.
Since you're beginner, I would assume, you should look toward something like this instead:
a_1_add = "message 1"
a_2_add = "message 2"
container = [a_1_add, a_2_add]
for element in container:
print(element)
Note, you can still access the contents of both variables a_1_add and a_2_add, change them, add more variables to the container and so on.
Maybe you can use the for loop to loop through all the variables.
var1 = “message 1”
var2 = “message 2”
var3 = “message 3”
for i in [var1, var2, var3]:
print(i)
Edit:
Yes, as #juanpa.arrivillage suggested , string list dictionary etc. are all data types (built in) in Python. Variables are user-defined, just a name representing the value assigned to it.
I think I get what you mean: like create variables using whilè loop? If so, I m afraid that it is not possible. Maybe you can use an array to contain those all values instead ? and access them using index or slicing.
x = 1
all_val = [] # this is a list here
while x < 3:
all_val.append(f"a_{x}_add")
x += 1
print(all_val[0])
print(all_val[1])
print(all_val[1:])
Hope it can answer you question.

Cannot understand how this Python code works

I found this question on HackerRank and I am unable to understand the code(solution) that is displayed in the discussions page.
The question is:
Consider a list (list = []). You can perform the following commands:
insert i e: Insert integer at position .
print: Print the list.
remove e: Delete the first occurrence of integer .
append e: Insert integer at the end of the list.
sort: Sort the list.
pop: Pop the last element from the list.
reverse: Reverse the list.
Even though I have solved the problem using if-else, I do not understand how this code works:
n = input()
slist = []
for _ in range(n):
s = input().split()
cmd = s[0]
args = s[1:]
if cmd !="print":
cmd += "("+ ",".join(args) +")"
eval("slist."+cmd)
else:
print slist
Well, the code takes advantage of Python's eval function. Many languages have this feature: eval, short for "evaluate", takes a piece of text and executes it as if it were part of the program instead of just a piece of data fed to the program. This line:
s = input().split()
reads a line of input from the user and splits it into words based on whitespace, so if you type "insert 1 2", s is set to the list ["insert","1","2"]. That is then transformed by the following lines into "insert(1,2)", which is then appended to "slist." and passed to eval, resulting in the method call slist.insert(1,2) being executed. So basically, this code is taking advantage of the fact that Python already has methods to perform the required functions, that even happen to have the same names used in the problem. All it has to do is take the name and arguments from an input line and transform them into Python syntax. (The print option is special-cased since there is no method slist.print(); for that case it uses the global command: print slist.)
In real-world code, you should almost never use eval; it is a very dangerous feature, since it allows users of your application to potentially cause it to run any code they want. It's certainly one of the easier features for hackers to use to break into things.
It's dirty code that's abusing eval.
Basically, when you enter, for example, "remove 1", it creates some code that looks like sList.remove(1), then gives the created code to eval. This has Python interpret it.
This is probably the worst way you could solve this outside of coding competitions though. The use of eval is entirely unnecessary here.
Actually I Find some error in the code, but I came to an understanding of how this code runs. here is it:
input :
3
1 2 3
cmd = 1 + ( 2 + 3)
then eval(cmd) i.e., eval("1 + (2 + 3)") which gives an output 6
another input:
4
4 5 6 2
cmd = 4 + ( 5 + 6 + 2)
eval(cmd)
if __name__ == '__main__':
N = int(raw_input())
lst=[]
for _ in range(N):
cmd, *line = input().split()
ele= list(map(str,line))
if cmd in dir(lst):
exec('lst.'+cmd+'('+','.join(ele)+')')
elif cmd == 'print':
print(lst)
else:
print('wrong command', cmd)

Randomly generating math questions

My task is to produce a code that greets the user and asks their name storing their name as username. Then generates 2 random numbers and an operation. The question is asked to the user. After that it checks if the users answer is correct or not also adding 1 to questionsAsked. If it is correct, 1 is added to correctAnswers. If it is incorrect, the user is told so with the correct answer. The program should end after 10 questions (hence the while questionAsked > 11). The user should be given their username and how many questions they got correct.
My problem is when I run the code,it comes up with NameError: name 'questionAsked' is not defined. I'm struggling to work out how else I could define questionAsked.
Here is what I've done so far:
import random
import math
def test():
Username=input("What is your name?")
print ("Welcome"+Username+" to the Arithmetic quiz")
num1=random.randint(1, 10)
num2=random.randint(1, 10)
Ops = ['+','-','*']
Operation = random.choice(ops)
num3=int(eval(str(num1) + operation + str(num2)))
print("What is" +" "+str(num1) + operation +str (num2,"?"))
userAnswer= int(input("Your answer:"))
if userAnswer != num3:
print("Incorrect. The right answer is"+" "+(num3))
return False
else:
print("correct")
return True
correctAnswers=0
questionsAsked=0
while questionAsked > 11:
if test () == True:
questionsAnswered +=1
correctAnswers +=1
if test () == False:
questionsAnswered +=1
You have a test while questionAsked > 11 but don't use that name anywhere else in your code. You certainly never defined it. You probably wanted to test questionsAsked (with an s) instead.
There are other problems, however. The loop should continue while you have fewer than 11 questions asked, not more. You also call test() twice, you should only call it once each loop. In your loop you use questionsAnswered but never defined that either and don't increment questionsAsked; you probably meant to increment the latter:
correctAnswers=0
questionsAsked=0
while questionsAsked < 10:
if test():
correctAnswers +=1
questionsAsked +=1
Now test() is only called the once. Both your branches incremented questionsAsked, I moved that out of the tests, and now you no longer need to check if the test failed.
Since you start counting at zero, you want to test for < 10, not 11.
Instead of a while loop, you could use a for loop using the range() function:
for question_number in range(10):
if test():
correctAnswers +=1
Now the for loop takes care of counting the number of questions asked, and you no longer need to increment a variable manually.
Next, you need to move the username handling out of the test() function. You don't need to ask the user for their name each time. Ask for the name once, before the loop, so that you can access the user's name after the 10 questions:
def test():
num1=random.randint(1, 10)
num2=random.randint(1, 10)
# ... etc.
Username = input("What is your name?")
print("Welcome", Username, "to the Arithmetic quiz")
correctAnswers = 0
for question_number in range(10):
if test():
correctAnswers +=1
# print the username and correctAnswers
You need to be careful about your names in the test() function too; you define the names Ops and Operation but try to use them as ops and operation instead. That won't work, you need to use the same case everywhere to refer to those names. The Python style guide recommends you use all lowercase with underscores for local names, to distinguish them from class names (which use CamelCase, initial uppercase letters and no spaces between words).
Next problem: you are using str() with two arguments here:
print("What is" +" "+str(num1) + operation +str (num2,"?"))
That won't work; a two-argument str() call is meant for decoding bytes to a Unicode string.
Rather than use string concatenation, just pass your values to print() as separate arguments. The function will take care of converting things to strings and adds spaces between separate arguments for you:
print("What is", num1, operation, num2, "?")
Now there will be a space between num2 and the "?" but that is not that big a problem. You can use the str.format() method to create a string with placeholders where arguments to the method are filled in for you, again converting to strings automatically. This allows you to control spaces more directly:
print("What is {} {} {}?".format(num1, operation, num2))
The three arguments are placed where each {} appears, in order.
You have many discrepancies in variable names and indentation. Remember Python is case sensitive. And by the way, the condition in your while loop will cause your program not to ask any questions.
So for example, you created a list of operations called Ops and then used the random module to select an operation from ops. Python will inevitably throw an error, as ops is not actually defined. Instead, you should use Ops because that is the variable you actually declared, with a capital letter. Again, Python is case sensitive.
Likewise, Python recognizes a difference between questionAsked and questionsAsked. It's one or the other, so choose a name and be consistent.

Python - Converting a Number to a Letter without an if statement

I am making a program for my own purposes (a naming program) that completely generates a random name. The problem is I cannot assign a number to a letter, so as a being 1 and z being 26, or a being 0 and z being 25. It gives me a SyntaxError. I need to assign this because the random integer (1,26) triggers a letter (if the random integer is 1, select A) and prints the name.
EDIT:
I have implemented your advice, and it works, I am grateful for this, but I wish to have my program create readable names, or more procedural. Here is an example of a name after I tweaked my program: ddjau. Now that doesn't look like a name, so I want it my program to work as if it were creating REAL names, like Samuel or other common names. Thanks!
EDIT (2):
Thanks, Adam, but I need a sort of 'seed' for the user to enter for the start of the name is. (Seed = A, Name = Adam. Seed = G, Name = George.) Should I do this by searching the file line by line, at the very beginning? If so, how do I do this?
Short Answer
Look into Python dictionaries to allow the 1 = 'a' type assignments. Below I have working example that would generate a random name based on gender and a 'litter'.
Disclaimer
I do not fully understand (via the code) what you're trying to accomplish with char/ord and a random letter. Also note having absolutely no idea of your design goals or requirements, I have made the example more complex than it may need to be for instructional purposes.
Additional Resources
* Python Docs for dictionary
* Using Python dictionary relationship to search both ways
In response to the last edit
If you are looking to build random 'real' names, I think your best bet will be to use a large list of names and just pick a random one. If I were you I'd look into something linking to the census results: males and females. Note that male_names.txt and female_names.txt are a copy of the list found at the census website. As a disclaimer, I'm sure there is a more efficient way to load / read the file. Just use this example as a proof on concept.
Update
Here's a quick and dirty way to seed the random values. Again I am not sure that this is the most pythonic way or most efficient way, but it works.
Example
import random
import time
def get_random_name(gender, seed):
if(gender == 'male'):
file = 'male_names.txt'
elif(gender == 'female'):
file = 'female_names.txt'
fid = open(file,'r')
names = []
total_names = 0
for line in fid:
if(line.lower().startswith(seed)):
names.append(line)
total_names = total_names + 1
random_index = random.randint(0,total_names)
return names[random_index]
if (__name__ == "__main__"):
print 'Welcome to Name Database 2.2\n'
print '1. Boy'
print '2. Girl'
bog = raw_input('\nGender: ')
print 'What should the name start with?'
print 'A, Ab, Abc, B, Ba, Br, etc...'
print ''
l = raw_input('Leter(s): ').lower()
new_name = ''
if bog == '1': # Boy
print get_random_name('male',l)
elif bog == '2':
print get_random_name('female',l)
Output
Welcome to Name Database 2.2
1. Boy
2. Girl
Gender: 2
What should the name start with?
A, Ab, Abc, B, Ba, Br, etc...
Leter(s): br
BRITTA
chr (see here) and ord (see here) are the two functions you're looking for (though you already seem to know about the latter). Follow those links for a more detailed explanation.
The first gives you a one-character string based on the integer, the second does the reverse operaion (technically, it handles Unicode as well, which chr doesn't, though you have unichr for that if you need it).
You can base your code on the following:
ch = "E"
print ord (ch) - ord ("A") + 1 # should give 5 for the fifth letter
val = 7
print chr (val + ord ("A") - 1) # should give G, the seventh letter
I'm not entirely sure what you're trying to do, but you can convert a number into a letter with the chr() function. chr() takes an ASCII code, so if you want to use the range [0, 25] instead you can adapt it like so:
chr(25 + ord('a')) # 'z'

Python - display different output if the input is a letter or a number

I want to print the result of the equation in my if statement if the input is a digit and print "any thing" if it is a letter.
I tried this code, but it's not working well. What is wrong here?
while 1:
print '\tConvert ciliuse to fehrenhit\n'
temp = input('\nEnter the temp in C \n\t')
f = ((9/5)*temp +32)
if temp.isdigit():
print f
elif temp == "quit" or temp == "q" :
break
elif temp.isalpha() :
print ' hhhhhhh '
You need to go through your code line by line and think about what type you expect each value to be. Python does not automatically convert between, for example, strings and integers, like some languages do, so it's important to keep types in mind.
Let's start with this line:
temp = input('\nEnter the temp in C \n\t')
If you look at the documentation for input(), input() actually calls eval() on what you type in in Python 2.x (which it looks like you're using). That means that it treats what you type in there as code to be evaluated, just the same as if you were typing it in the shell. So if you type 123, it will return an int; if you type 'abc', it will return a str; and if you type abc (and you haven't defined a variable abc), it will give you an error.
If you want to get what the user types in as a string, you should use raw_input() instead.
In the next line:
f = ((9/5)*temp +32)
it looks like you're expecting temp to be a number. But this doesn't make sense. This line gets executed no matter what temp is, and you're expecting both strings containing digits and strings containing letters as input. This line shouldn't go here.
Continuing on:
if temp.isdigit():
isdigit() is a string method, so here you're expecting temp to be a string. This is actually what it should be.
This branch of the if statement is where your equation should go, but for it to work, you will first have to convert temp to an integer, like this:
c = int(temp)
Also, to get your calculation to work out right, you should make the fraction you're multiplying by a floating-point number:
f = ((9/5.0)*c +32)
The rest of your code should be okay if you make the changes above.
A couple of things first - always use raw_input for user input instead of input. input will evaluate code, which is potentially dangerous.
while 1:
print "\tConvert ciliuse to fehrenhit\n"
temp = raw_input("\nEnter the temp in C \n\t")
if temp in ("quit", "q"):
break
try:
f = ((9.0 / 5.0) * float(temp) + 32)
except ValueError:
print "anything"
Instead of using isalpha to check if input is invalid, use a catch clause for ValueError, which is thrown when a non-numerical value is used.
Why isn't it working? Are you getting an error of any kind?
Straight away I can see one problem though. You are doing the calculation before you verify it as a number. Move the calculation to inside the if temp.isdigit().
Take a look at this for some examples:
http://wiki.python.org/moin/Powerful%20Python%20One-Liners
OK, this works. Only problem is when you quit, you get dumped out of the interpreter.
while 1: import sys; temp=raw_input('\nEnter the temp in C \n\t'); temp.isdigit() and sys.stdout.write('%lf' %((9./5)*float(temp)+32)) or temp=='q' and sys.exit(0) or sys.stdout.write(temp)

Categories