Using var() to instantiate object from user input. Syntax error - python

I've made these classes and now I'm trying to make a function that allows you to instantiate a new object from data a user inputs. But I'm getting syntax errors with using var()
The class structure is that there is one main with two sub-classes. The main, "Gokemon" is:
class Gokemon:
def __init__(self,NAME,TYPE,HEALTH,POWER): #Contructor #Mayb think about using dict key words
self._Name = str(NAME)
self._Type = str(TYPE) #Water, Earth, Fire or Flying. Used in Battle() to allow adders
self._HP = int(HEALTH) #Health Points
self._DP = int(POWER) #Power Points - attacking power
and the two sub-classes are named "Tame" and "Wild".
class Tame(Gokemon):
def __init__(self,NAME,TYPE,HEALTH,POWER):
Gokemon.__init__(self,NAME,TYPE,HEALTH,POWER)
self._Owner = ""
self._Time = 0 #How long have they owned it
class Wild(Gokemon):
def __init__(self,NAME,TYPE,HEALTH,POWER):
Gokemon.__init__(self,NAME,TYPE,HEALTH,POWER)
The function for making the new object by user input is as follows:
def NewGokemon():
n = input("What's its name?: ")
while True:
t = input("what's its type?: ")
if t == "Water" or t == "Fire" or t=="Earth" or t =="Flying":
break
else:
print("please try again, the types include:\nFire\nWater\nEarth\nFlying")
while True:
h = input("How many Health Points(HP) does it have")
try:
int(h)/2
except ValueError:
print("Sorry please input a numerical value")
else:
break
while True:
p = input("How many Health Points(HP) does it have")
try:
int(p)/2
except ValueError:
print("Sorry please input a numerical value")
else:
break
while True:
dom = input("Is the Gokemon tame(input t) or wild(input w)?")
if dom =="t":
return var()[n] = Tame(n,t,h,p)
if dom == 'w':
return var()[n] = Wild(n,t,h,p)
The function is fine until at the bottom, when im compiling to execute my Editor (VS code) says.
File "c:\Users\rufar\Desktop\python\little projects\Gokemon - learning class\Gokemon.py", line 38
return var()[n] = Tame(n,t,h,p)
^
SyntaxError: invalid syntax
What am i doing wrong? Is there a better way of doing this?

replaced the whole bit with vars() with this:
while True:
dom = input("Is the Gokemon tame(input t) or wild(input w)?")
if dom =="t":
globals()[n] = Tame(n,t,h,p)
return n
elif dom == 'w':
globals()[n] = Wild(n,t,h,p)
return n
else:
print("Did not understand input")
And now it works fine.

Related

How to give variable values from a function to another function?

Im making a "game" for practice. Its a basic guess game, but i wanted to make the game only with functions. This is my problem (for ex.):
function 1:
variablaA
#some other code
function 2:
variableB
variableC = varibleA + variableB
#some other code
I have tried too goole about objects and classes but im not sure i understand what im doing right now.
import random
import sys
min = 1
max = 99
guessed_number = random.randint(min, max)
class functions:
def __init__(game, difficulty, lifes):
game.difficulty = difficulty
game.lifes = lifes
def GameDiff(hardness):
#Setting game difficulty
print "Select difficulty : \n 1; Easy \n 2; Medium \n 3; Hard \n"
difficulty = raw_input()
if difficulty == "1":
print "Its just the beginning"
lifes = 15
elif difficulty == "2":
lifes = 10
elif difficulty == "3":
lifes = 5
else:
print "This isn't an option try again"
GameDiff(hardness)
def core(basic):
#The core of the game
print "I guessed a number..."
player_number = int(raw_input("Whats the number I thinking of?"))
constant = 1
GameTime = 1
while GameTime == constant:
if player_number < guessed_number:
print "Your number is smaller than my guessed number"
print "Try to duplicate your number (But maybe Im wrong)"
player_number = int(raw_input("Make your tip again\n"))
elif player_number > guessed_number:
print "Your number is bigger than my guessed number"
print "Try to half your number (But maybe Im wrong)"
player_number = int(raw_input("Make your tip again\n"))
else:
GameTime = 0
print "You guessed it! Congratulations"
def main(self):
#The whole game only with functions
functions.GameDiff()
functions.core()
Function = functions()
Function.main()
if you are defining function with parameters, you need to pass data(parameters) into a function when you call it
example:
def my_function(name):
print("my name is " + name)
my_function("Kevin")
in your case you define:
def GameDiff(hardness):
def core(basic):
which are expecting parameters
and when you are calling those funcitions, you are doing that on wrong way:
def main(self):
#The whole game only with functions
functions.GameDiff()
functions.core()
Function = functions()
you need to pass parameters
example:
functions.GameDiff(5)
functions.core(1)
Function = functions(1,5)
NOTE: good practice will be to use self instead of game
def __init__(self, difficulty, lifes):
self.difficulty = difficulty
self.lifes = lifes
they are just two different kinds of class elements:
Elements outside the init method are static elements; they belong
to the class. They're shared by all instances.
Elements inside the init method are elements of the
object (self); they don't belong to the class.Variables created inside init (and all other method functions) and prefaced with self. belong to the object instance.

Integer Validation Python

I need to add a validation whilst in a while loop.
However when I use this validation it doesn't work and instead only comes up with the error message saying I haven't used a base 10/an integer when I want it to come up with the validation error message and let the user try again.
I don't know if having it in a while loop makes the validation I use any different, does it?
Also do I need to change this "def inputNumber(message):" to what my input is stored as?
And this "userInput = int(input(message))" to what my input is stored as?
import time
import random
question = 0
score = 0
name = input("What is your full name?")
print ("Hello " + name, "welcome to The Arithmetic Quiz. Use integers to enter the answer!")
time.sleep(2)
operands1 = list(range(2, 12))
operators = ["+","-","x"]
operands2 = list(range(2, 12))
while question < 10:
operand1 = random.choice(operands1)
operand2 = random.choice(operands2)
operator = random.choice(operators)
def inputNumber(message):
while True:
try:
userInput = int(input(message))
except ValueError:
print("Not an integer! Try again.")
continue
else:
return userInput
break
user_answer =int(input('{} {} {} = '.format(operand1, operator, operand2)))
I doubt you want to have your function definitions within a while loop like you're doing here:
while question < 10:
...
def inputNumber(message):
...
Instead, you can define the function outside the loop and call it x number of times from a loop elsewhere. E.g.
def inputNumber(message):
...
return userInput
while question < 10:
# pick random numbers/operators
...
# call inputNumber() with numbers/operators as message. Return user_answer
user_answer = int(inputNumber('{} {} {} = '.format(operand1, operator, operand2)))
# check if the answer is correct
...
# increment question so it doesn't run infinitely
question += 1
#user6104134 has already solved this problem; however, I'd like to provide an answer for anyone else having similar issues.
Try this solution
import random
import time
question = 0
score = 0
def inputnumber(prompt):
while True:
response = raw_input(prompt)
try:
if isinstance(response, int):
return int(response)
else:
print "Not an integer! Try again."
except ValueError:
print "Not an integer! Try again."
name = raw_input("What is your full name? ")
print ("Hello " + name, "welcome to The Arithmetic Quiz. Use integers to enter the answer!")
time.sleep(2)
operands1 = list(range(2, 12))
operators = ["+", "-", "x"]
operands2 = list(range(2, 12))
while question < 10:
operand1 = random.choice(operands1)
operand2 = random.choice(operands2)
operator = random.choice(operators)
user_answer = int(inputnumber('{} {} {} = '.format(operand1, operator, operand2)))
question += 1
Issues
First, you should declare function definitions outside of your script and call the function by identifier 'inputNumber()'
Also notice the slight change in Try/Except, and the PEP 8 Style Guide compliant formatting.

Saving of Information in Python Along with Retrieving It

The purpose of the two programs is to have twitter.py manage tweet.py by having the 5 most recent tweets that are saved in the program twitter.py to show up once you search and find it. There are four options, make a tweet, view recents tweets, search a tweet and quit. I'm having trouble saving because it keeps saying no recent tweets are found. Also I'm having trouble with the fact that I can't search for my tweets but that is probably the same reason as my first problem because they aren't being saved correctly. Thank you please help!!
tweet.py
import time
class tweet:
def __init__(self, author, text):
self.__author = author
self.__text = text
self.__age = time.time()
def get_author(self):
return self.__author
def get_text(self):
return self.__text
def get_age(self):
now = time.time()
difference = now - self.__time
hours = difference // 3600
difference = difference % 3600
minutes = difference // 60
seconds = difference % 60
# Truncate units of time and convert them to strings for output
hours = str(int(hours))
minutes = str(int(minutes))
seconds = str(int(seconds))
# Return formatted units of time
return hours + ":" + minutes + ":" + seconds
twitter.py
import tweet
import pickle
MAKE=1
VIEW=2
SEARCH=3
QUIT=4
FILENAME = 'tweets.dat'
def main():
mytweets = load_tweets()
choice = 0
while choice != QUIT:
choice = get_menu_choice()
if choice == MAKE:
add(mytweets)
elif choice == VIEW:
recent(mytweets)
elif choice == SEARCH:
find(mytweets)
else:
print("\nThanks for using the Twitter manager!")
save_tweets(mytweets)
def load_tweets():
try:
input_file = open(FILENAME, 'rb')
tweet_dct = pickle.load(input_file)
input_file.close()
except IOError:
tweet_dct = {}
return tweet_dct
def get_menu_choice():
print()
print('Tweet Menu')
print("----------")
print("1. Make a Tweet")
print("2. View Recent Tweets")
print("3. Search Tweets")
print("4. Quit")
print()
try:
choice = int(input("What would you like to do? "))
if choice < MAKE or choice > QUIT:
print("\nPlease select a valid option.")
except ValueError:
print("\nPlease enter a numeric value.")
return choice
def add(mytweets):
author = input("\nWhat is your name? ")
while True:
text = input("what would you like to tweet? ")
if len(text) > 140:
print("\ntweets can only be 140 characters!")
continue
else:
break
entry = tweet.tweet(author, text)
print("\nYour tweet has been saved!")
def recent(mytweets):
print("\nRecent Tweets")
print("-------------")
if len(mytweets) == 0:
print("There are no recent tweets. \n")
else:
for tweets in mytweets[-5]:
print(tweets.get_author, "-", tweets.get_age)
print(tweets.get_text, "\n")
def find(mytweets):
author = input("What would you like to search for? ")
if author in mytweets:
print("\nSearch Results")
print("----------------")
print(tweet.tweet.get_author(), - tweet.tweet.get_age())
print(tweet.tweet.get_text())
else:
print("\nSearch Results")
print("--------------")
print("No tweets contained ", author)
def save_tweets(mytweets):
output_file = open(FILENAME, 'wb')
pickle.dump(mytweets, output_file)
output_file.close()
main()
In twitter.py:add_tweets, mytweets is passed into the function and entry is created, but it is never added to mytweets. The created entry is lost after the function returns.
Your question was:
I'm having trouble saving because it keeps saying no recent tweets are
found.
Function add does not seem to be adding tweets anywhere. It creates a tweet.tweet instance, but it does not do anything with it.
You probably want to add the tweet to mytweets?
Another problem:
You initialize mytweets as a dicionary (tweet_dct = {}), but later you use it as a list (mytweets[-5]). It should be a list from start. And you probably want last five tweets (mytweets[-5:]), not just the fifth from the end.
On the sidenotes:
What you have here is not "two programs" - it is one program in two python files, or "modules"
Although there is nothing wrong with having getters (functions like get_author), there is no need for them in Python (see How does the #property decorator work?). Do youself a favour and keep it simple, e.g.:
class Tweet:
def __init__(self, author, text):
self.author = author
self.text = text
self.creation_time = time.time()
def get_age_as_string(self):
# your code from get_age
There will be time when you need private variables. When that happens, use a single leading underscore (self._author) until you fully understand what double underscore does and why.
Pickle is probably not the best way to store information here, but it is a good start for learning.

What is wrong with my defintion of the function prompt_int?

I have been trying to program a maths quiz that both works and is as efficient as possible. Looking over my code I saw I had a lot of integer inputs and that lead to me having the program to ask the question/exit the system if the criteria isn't met, so to help me I thought that it would be useful to create a new function. Here is my attempt:
def prompt_int(prompt=''):
while True:
if status == prompt_int(prompt=''):
val = input(prompt)
if val in (1,2):
return int(val)
return true
elif status != prompt_int(prompt=''):
val = input(prompt)
if val in (1,2,3):
return int(val)
return true
else:
print("Not a valid number, please try again")
However, when I try to implement this function around my code it doesn't work properly as it says that status isn't defined however, when I do define status it goes into a recursion loop. How can I fix this problem?
Here is my original code before i try to implement this function:
import sys
import random
def get_bool_input(prompt=''):
while True:
val = input(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
sys.exit("Not a valid input (yes/no is expected) please try again")
status = input("Are you a teacher or student? Press 1 if you are a student or 2 if you are a teacher")# Im tring to apply the new function here and other places that require integer inputs
if status == "1":
score=0
name=input("What is your name?")
print ("Alright",name,"welcome to your maths quiz."
"Remember to round all answer to 5 decimal places.")
level_of_difficulty = int(input(("What level of difficulty are you working at?\n"
"Press 1 for low, 2 for intermediate "
"or 3 for high\n")))
if level_of_difficulty not in (1,2,3):
sys.exit("That is not a valid level of difficulty, please try again")
if level_of_difficulty == 3:
ops = ['+', '-', '*', '/']
else:
ops = ['+', '-', '*']
for question_num in range(1, 11):
if level_of_difficulty == 1:
number_1 = random.randrange(1, 10)
number_2 = random.randrange(1, 10)
else:
number_1 = random.randrange(1, 20)
number_2 = random.randrange(1, 20)
operation = random.choice(ops)
maths = round(eval(str(number_1) + operation + str(number_2)),5)
print('\nQuestion number: {}'.format(question_num))
print ("The question is",number_1,operation,number_2)
answer = float(input("What is your answer: "))
if answer == maths:
print("Correct")
score = score + 1
else:
print ("Incorrect. The actual answer is",maths)
if score >5:
print("Well done you scored",score,"out of 10")
else:
print("Unfortunately you only scored",score,"out of 10. Better luck next time")
class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
while class_number not in ("1","2","3"):
print("That is not a valid class, unfortunately your score cannot be saved, please try again")
class_number = input("Before your score is saved ,are you in class 1, 2 or 3? Press the matching number")
else:
filename = (class_number + "txt")
with open(filename, 'a') as f:
f.write("\n" + str(name) + " scored " + str(score) + " on difficulty level " + str(level_of_difficulty))
with open(filename, 'a') as f:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
f.close()
lines.sort()
if get_bool_input("Do you wish to view previous results for your class"):
for line in lines:
print (line)
else:
sys.exit("Thanks for taking part in the quiz, your teacher should discuss your score with you later")
if status == "2":
class_number = input("Which classes scores would you like to see? Press 1 for class 1, 2 for class 2 or 3 for class 3")
if class_number not in (1,2,3):
sys.exit("That is not a valid class")
filename = (class_number + "txt")
with open(filename, 'a') as f:
f = open(filename, "r")
lines = [line for line in f if line.strip()]
f.close()
lines.sort()
for line in lines:
print (line)
Well, just a part:
def prompt_int(prompt=""):
while True:
val = input(prompt)
if val in ("1", "2"):
return int(val), True
Will ask again and again. And return when the user enter "1" or "2"!
But better: "if val in "12":
def prompt_int(prompt=""):
while True:
val = input(prompt)
if val.isdigit():
return int(val)
Hi if you dont want to have valid values send to your you could change your code as the function above.
But you could also change it to do the system exits:
def prompt_int(prompt="", authorized=()):
while True:
val = raw_input(prompt)
if val.isdigit():
if int(val) in authorized:
return int(val)
else:
sys.exit("Bla bla bla too bad")
def prompt_int(prompt=''):
while True:
if status == prompt_int(prompt=''):
This line will look for the name "status" in the global namespace (module's namespace), and raise a NameError if there's no global variable named 'status'.
If there's one, it will then recursively calls prompt_int without any possible termination, resulting theoretically in an endless recursion, but practically (in CPython at least) in a RuntimeError when it will hit the maximum recursion depth.
There are also quite a few other things that won't work as you expect:
val = input(prompt)
if val in (1,2):
In Python 3.x, val will be a string, so it will never compare equal to an int. In Python 2.x, input() is a shortcut for eval(raw_input()), which might return an int, but is also a huge security flaw since it unconditionnally execute untrusted code.
return int(val)
return true
The second return statement will never be executed, obviously, since the function will exit at the first one.
A simpler implementation might look like this:
# rebinds raw_input to input for python < 3
import sys
if sys.version_info.major < 3:
input = raw_input
def prompt_int(prompt='', choices=None):
while True:
val = input(prompt)
try:
val = int(val)
if choices and val not in choices:
raise ValueError("{} is not in {}".format(val, choices))
return val
except (TypeError, ValueError) as e:
print(
"Not a valid number ({}), please try again".format(e)
)
While we're at it, there's room for improvement in other parts of your code. Let's start with this:
def get_bool_input(prompt=''):
while True:
val = input(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
sys.exit("Not a valid input (yes/no is expected) please try again")
First point: your naming is not consistent. If your other function is named prompt_int, this one should be named prompt_bool. Also, you have one function (prompt_int) looping forever and the other one exiting the whole program on invalid input, which is another inconsistency. If you want to allow the user to exit on any prompt, provide an explicit option for it, ie:
def prompt_bool(prompt, quit='Q'):
prompt += " (hit '{}' to exit) : ".format(quit)
while True:
val = input(prompt).strip().upper()
if val == quit:
sys.exit("Goodbye")
elif val == 'yes':
return True
elif val == 'no':
return False
else:
print "Invalid input '{}', please try again".format(val)
Of course you then want to provide the same option in prompt_int(), which leads to a more generic function:
def get_input_or_quit(prompt, quit="Q"):
prompt += " (hit '{}' to exit) : ".format(quit)
val = input(prompt).strip()
if val.upper() == quit:
sys.exit("Goodbye")
return val
def prompt_bool(prompt):
while True:
val = get_input_or_quit(prompt).lower()
if val == 'yes':
return True
elif val == 'no':
return False
else:
print "Invalid input '{}', please try again".format(val)
And of course you also replace the call to input by a call to get_input_or_quit in prompt_int.
We could go on for long - splitting all your code in distinct, self-contained function, writing a "main()" function to drive them (instead of having the "main" part at the top level), and obviously using the operator module instead of eval().

Doing a sort of a loop while avoiding a certain prerequisite (beginner/python)

A beginner's problem, here it goes:
I'm writing a program which keeps records of a game of darts. The user types in the players and their respective scores. It's possible to do a query about a player's scores and ask the program for the best overall score between all the players. I have the following functions:
add_score
return_players_score
return_best_score
exit_program
main
In main(), we begin by creating a new empty dictionary (say, players = {}). Then we ask the user to input a number that takes him/her to the function of choice (1: add_score etc.).
Now, once we're in add_score and have added a key:value pair (player:score), we need to go back to inputting the number taking to the function of choice. I implemented it simply by writing main() to the end of add_score.
That, however, takes us to the beginning, where there's players = {} and thus whatever data we input in add_score gets wiped out. This then affects other functions and the program remains useless as long as it forgets everything right away. How to solve this?
I'd paste the actual code but it's not in English and it's an assignment anyway...
Thanks.
Rather than calling main() from each of your other functions, you should just return (or run off the end of the function, which is equivalent to return None). Since you need the main function to run things repeatedly, you should use a loop.
def main():
players = {}
while True: # loop forever (until a break)
choice = input("what do you want to do (1-4)")
if choice == "1":
add_score(players)
elif choice == "2":
return_players_score(players)
#...
elif choice == "4":
break # break out of the loop to quit
else:
print("I didn't understand that.")
If you have a loop that does something like the following..
example:
while True:
players = {}
some code adding to players
This loop will always reset players to {}
However, if you do:
players = {}
while something:
some code adding to players
then players is not being reset at the start of each iteration through the loop
But your question is not clear
If you have something like this:
def add_score(dicccionary):
#do something with diccionary
main()
def main():
dicccionary = {}
while something:
option = input("option")
if option == 1:
addscore(dicccionary)
else:
#otherfunction
main()
your reset problem can be solve like:
dicccionary = {} #global variable
def add_score():
#do something with diccionary
main()
def main():
option = input("option")
if option == 1:
addscore()
else:
#otherfunction
main()
By the way, you shouldn't make it this way, try something as:
dicccionary = {} #global variable
def add_score():
#do something with diccionary
def main():
while somecondition:
option = input("option")
if option == 1:
addscore()
else:
#otherfunction
main()
If I was doing it for real then I would go for something like:
import sys
class ScoreKeeper(object):
def init(self):
self.scores = {}
def add_score(self, player, score):
self.scores[player] = score
def _print_player_score(self, player, score):
print 'player:', player, 'score:', score
def print_scores(self):
for player, score in self.scores.items():
self._print_player_score(player, score)
def best_score(self):
best, player = 0, "no player"
for player, score in self.scores.items():
if score > best:
best, player = score, player
self._print_player_score(player, best)
if __name__ == '__main__':
scorer = ScoreKeeper()
quit = lambda: sys.exit()
choices = quit, scorer.add_score, scorer.print_scores, scorer.best_score
def help():
print 'Enter choice:'
for index, c in enumerate(choices):
print '%d) %s' % (index, c.__name__)
def get_integer(prompt):
res = raw_input(prompt)
try:
return int(res)
except:
print 'an integer is required'
return get_integer(prompt)
def get_choice():
choice = get_integer('choice? ')
if not 0 <= choice < len(choices):
help()
return get_input()
return choice
help()
choice = get_choice()
while(choice):
args = []
if choices[choice] == scorer.add_score:
args.append(raw_input('player name? '))
args.append(get_integer('score? '))
choices[choice](*args)
choice = get_choice()
quit()

Categories

Resources