I am trying to create a def file within a py file that is external eg.
calls.py:
def printbluewhale():
whale = animalia.whale("Chordata",
"",
"Mammalia",
"Certariodactyla",
"Balaenopteridae",
"Balaenoptera",
"B. musculus",
"Balaenoptera musculus",
"Blue whale")
print("Phylum - " + whale.getPhylum())
print("Clade - " + whale.getClade())
print("Class - " + whale.getClas())
print("Order - " + whale.getOrder())
print("Family - " + whale.getFamily())
print("Genus - " + whale.getGenus())
print("Species - " + whale.getSpecies())
print("Latin Name - "+ whale.getLatinName())
print("Name - " + whale.getName())
mainwindow.py:
import calls
import animalist
#import defs
keepgoing = 1
print("Entering main window")
while True:
question = input("Which animal would you like to know about?" #The question it self
+ animalist.lst) #Animal Listing
if question == "1":
print(calls.printlion())#Calls the animal definition and prints the characteristics
if question == "2":
print(calls.printdog())
if question == "3":
print(calls.printbluewhale())
'''if question == "new":
def new_animal():
question_2=input("Enter the name of the new animal :")'''
What I am trying to do is that question == new would create a new def in the calls.py and that I would be able to add a name to the def and the attributes as well.
I was hoping you could lead me to a way of how to do this, and if it is not possible please just say and I will rethink my project :)
What you're trying to do here seems a bit of a workaround, at least in the way you're trying to handle it.
If i understood the question correctly, you're trying to make a python script that takes input from the user, then if that input is equal to "new", have it be able to define a new animal name.
You're currently handling this using a whole lot of manual work, and this is going to be extremely hard to expand, especially considering the size of the data set you're presumably working with (the whole animal kingdom?).
You could try handling it like this:
define a data set using a dictionary:
birds = dict()
fish = dict()
whales = dict()
whales["Blue Whale"] = animalia.whale("Chordata",
"",
"Mammalia",
"Certariodactyla",
"Balaenopteridae",
"Balaenoptera",
"B. musculus",
"Balaenoptera musculus",
"Blue whale")
whales["Killer Whale"] = ... # just as an example, keep doing this to define more whale species.
animals = {"birds": birds, "fish": fish, "whales": whales} # using a dict for this makes you independent from indices, which is much less messy.
This will build your data set. Presuming every whale class instance (if there is one) inherits properties from a presumptive Animal class that performs all the printing, say:
Class Animal():
# do some init
def print_data(self):
print("Phylum - " + self.getPhylum())
print("Clade - " + self.getClade())
print("Class - " + self.getClas())
print("Order - " + self.getOrder())
print("Family - " + self.getFamily())
print("Genus - " + self.getGenus())
print("Species - " + self.getSpecies())
print("Latin Name - "+ self.getLatinName())
print("Name - " + self.getName())
You can then have a Whale class:
class Whale(Animal)
Which now has the print_data method.
for whale in whales:
whales[whale].print_data()
With that out of the way, you can move on to adding input:
In your main.py:
while True:
question = input("Which animal would you like to know about?" #The question it self
+ animalist.lst) #Animal Listing
try:
id = int(question)
# if the input can be converted to an integer, we assume the user has entered an index.
print(calls.animals[animals.keys[id]])
except:
if str(question).lower() == "new": # makes this case insensitive
new_species = input("Please input a new species")
calls.animals[str(new_species)] = new_pecies
# here you should process the input to determine what new species you want
Beyond this it's worth mentioning that if you use dicts and arrays, you can put things in a database, and pull your data from there.
Hope this helps :)
Related
We're creating a small text-based bank application using python2, and we have to use the user's money for many of the functions. For instance: I create a variable a = 100 and I used the variable in the function with global a. But my teacher doesn't allow us to use the term global so i have to use something other than global.
For example:
a = 100
def withdraw():
global a
ko = input("Please enter the amount you want to withdraw:")
if ko > a:
print "You don't have " + " " + str(ko) + " " + "in your account."
print "Going back to main menu..."
else:
a = a - ko
print str(ko) + "Dollar" + "withdrawn from your account"
In this particular example, I'd simply pass a in, and return it back to the caller:
# Renamed a to balance
def withdraw(balance):
# Take input as before
return balance - ko
a = 100
a = withdraw(a)
Whenever possible, pass any relevant data in, and return any results back.
You can make the global variable (we are going to use account instead of a for this example) a local variable in your main and use it in every function that requires it. In this case something like this:
def withdraw(account):
# ... code here
account -= ko
print str(ko) + " Dollar withdrawn from your account"
return account
and you would call it like this
account = withdraw(account)
There are many ways you can avoid using global variables in your code for e.g. by using instance variables.
As your teacher suggests, you should avoid global variables because you may mistakenly declare another variable with the same name and then while reading the code, it will not be obvious which variable is getting accessed, making it hard to debug your code.
I suggest something similar to this:
class BankAccount():
def __init__(self, initial_balance):
self.balance = initial_balance
def withdraw(self, withdraw_amount=0):
if withdraw_amount > self.balance:
print "You don't have " + " " + str(withdraw_amount) + " " + "in your account."
print "Going back to main menu..."
else:
self.balance -= withdraw_amount
print str(withdraw_amount) + "Dollar" + "withdrawn from your account"
Following this you can create an instance of a bank account and withdraw form it in the following way:
bank_account = BankAccount(initial_balance=1000)
bank_account.withdraw(withdraw_amount=100)
In my code, the 'detentions' integer seems to be taking the value of the 'day' integer when calling new_week()
I have looked through the code and just cannot find what is causing it.
It is defined like:
def new_week(self, detentions, motivation):
print(colored(detentions, 'yellow'))
oldmotiv = motivation
for i in range(0, detentions):
motivation = motivation - 3
print(colored("Detentions: " + str(detentions), 'yellow'))
print(colored("Motivation: " + str(motivation), 'yellow'))
print(colored("End of week summary: ", 'green'))
lostmotiv = oldmotiv - motivation
print(colored("You lost " + str(lostmotiv) + " motivation!", 'green'))
detentions = 0
It is invoked like:
print("It's the weekend! What would you like to do?")
WorldSettings.new_week(detentions, day, motivation)
again = input("Continue? yes, no ")
again.lower()
day = 1
Full code is here, on Repl.it
In your code you are invoking the method as if it were a class method:
WorldSettings.new_week(detentions, day, motivation)
It should be as an instance method:
class_worldsettings.new_week(detentions, day, motivation)
Also, notice that you are invoking the method with 3 parameters, but your method is defined to only need 2 parameters (besides the elf`that is an implicit parameter):
def new_week(self, detentions, motivation)
So it should be:
def new_week(self, detentions, day, motivation)
Here is my code:
# This program makes the robot calculate the average amount of light in a simulated room
from myro import *
init("simulator")
from random import*
def pressC():
""" Wait for "c" to be entered from the keyboard in the Python shell """
entry = " "
while(entry != "c"):
entry = raw_input("Press c to continue. ")
print("Thank you. ")
print
def randomPosition():
""" This gets the robot to drive to a random position """
result = randint(1, 2)
if(result == 1):
forward(random(), random())
if(result == 2):
backward(random(), random())
def scan():
""" This allows the robot to rotate and print the numbers that each light sensors obtains """
leftLightSeries = [0,0,0,0,0,0]
centerLightSeries = [0,0,0,0,0,0]
rightLightSeries = [0,0,0,0,0,0]
for index in range(1,6):
leftLight = getLight("left")
leftLightSeries[index] = leftLightSeries[index] + leftLight
centerLight = getLight("center")
centerLightSeries[index] = centerLightSeries[index] + centerLight
rightLight = getLight("right")
rightLightSeries[index] = rightLightSeries[index] + rightLight
turnRight(.5,2.739)
return leftLightSeries
return centerLightSeries
return rightLightSeries
def printResults():
""" This function prints the results of the dice roll simulation."""
print " Average Light Levels "
print " L C R "
print "========================="
for index in range(1, 6):
print str(index) + " " + str(leftLightSeries[index]) + " " + str(centerLightSeries[index]) + " " + str(rightLightSeries[index])
def main():
senses()
pressC()
randomPosition()
scan()
printResults()
main()
So, I am getting this error when I run my program.
NameError: global name 'leftLightSeries' is not defined
I understand that I must be doing something wrong related to the return statement. I'm not sure if I can only return one variable at the end of a user-defined function. If that were to be true, then I should probably separate the scan(): function. Anyways, I would appreciate any help on how to fix this error. Also, this is the result that I am looking for when I successfully complete my program:
Click Here
I am looking to complete the average values like the picture shows, but I am not worried about them at this point, only the list of values from the light sensors. I do not need to reach those exact numbers, the numbers will vary in the simulator.
If you want to return multiple items from scan(), don't use three separate return statements. Instead, do this:
return leftLightSeries, centerLightSeries, rightLightSeries
Also, when you call the function, you have to assign variable(s) to the returned values; it won't automatically create new local variables with the same names. So in main, call scan() like this:
leftLightSeries, centerLightSeries, rightLightSeries = scan()
I am making a Recipe book, at the moment I have the ability to create a recipe, but now I am starting to build the module of searching and displaying stored recipes.
At the moment I have a .txt document with the contents along the lines of:
Williams Special Recipe
Ingredients:
bread: 120 grams
butter: 1234 grams
Recipe Serves: 12
I then ask the user how many they are serving and based on how many the recipe serves, I need to multiply all the ingredients quantity by that number. I then need to print that off with the full recipe again.
I was wondering how I would go about achieving this result, not asking specifically for a coded response as an answer, but I would greatly appreciate how I would approach this task and any specific functions required.
I have also included my code so far, I appreciate the fact it is incredibly un-organised at the moment, and probably hard to understand, but I included it for any reference.
(I have also created a .txt file of all the created recipes which will be implemented later on as a way of displaying to the user all recipes, but at the moment it is just set up for searching.)
#Recipe Task
import os.path
def file_(n):
if n == "listR" :
list_f = open("list_recipes.txt", "a+")
list_f.write(new_name + "\n")
if n == "oar": #open append read
f=open(new_name + ".txt","a+")
elif n == "c": #closes file
f.close()
def print_line(x): #ease of printing multiple lines to break up text
for c in range(x):
print ""
def new_ingredients(): #adding new ingredients
f.write("Ingredients:" + "\n" + "\n")
fin_ingredient = False
while fin_ingredient != True :
input_ingredient = raw_input("New ingredient:" + "\n").lower()
split_ingred = input_ingredient.split()
if input_ingredient == "stop": #stops asking questions when user types 'stop'
fin_ingredient = True
else :
f.write(split_ingred[0] + ":" + " " + split_ingred[1] + " " + split_ingred[2] + "\n")
def search_recipe(n): #searching for recipes
n = n + ".txt"
if os.path.isfile('/Users/wjpreston/Desktop/' + n) == True :
print "Recipe Found..."
found_recipe = open(n)
print found_recipe.read()
append_serving = raw_input("Would you like to change the number of people you are serving?" + "\n").lower()
if append_serving == "yes" :
appended_serving = input("How many would you like to serve?" + "\n")
with open(n) as f: #here is my issue - not sure where to go with this!!
list_recipe = f.readlines()
found_recipe.close()
else :
print "fail"
else:
print "No existing recipes under that name have been found."
print "Welcome to your Recipe Book"
print_line(3)
recipe_phase = raw_input("Are you 'creating' a recipe or 'viewing' an existing one?" + "\n").lower()
if recipe_phase == "creating":
new_name = raw_input("Name of Recipe: " + "\n")
file_("listR")
file_("oar")
f.write("------------" + "\n" + new_name + "\n" + "\n")
print "Ingrediants required in the format 'ingredient quantity unit' - type 'stop' to end process"
new_ingredients()
new_num = input("Number serving: ")
f.write("\n" + "Recipe Serves: " + str(new_num) + "\n" "\n" + "\n")
file_("c")
elif recipe_phase == "viewing":
search = raw_input("Search for recipe: ")
search_recipe(search)
I'm not the specialist in processing strings, but I'd approach your problem following way:
Save each ingredient on a new line.
Split the loaded string by "\n".
Then process the list with some for-loops while creating two dicts, one for the actual data
e.g. {"bread": 4, "butter": 7}
and one for the types of each ingredient:
e.g. {"bread": grams, "butter": grams}
The you should also save how many serves the recipe is written for, and maybe the order of the ingredients (dicts get stored in a random order):
e.g. ["bread", "butter"]
After that, you can ask your costumer how many serves he has and then finally calculate and print the final results.
for ing in ing_order:
print ing+":", ing_amount[ing]*requested_serves/default_seves, ing_types[ing]
...hopyfully you still have enough challange, and hopefully I understood your question correctly.
I was wondering how to fix this problem I am having with my first piece of OOP code. The problem lies within the attack method of the Snake class. I have two snakes in the game and am trying to get the snake to attack the other one. At the moment I am using two variables to note which Snake's turn it is, then use this to try and attack the other snake. However this is not working. Anyone have any idea how to solve this? Thank you so much.
class Snake:
hp=100
attack=25
defense=1
def set_name(self, name):
self.name=name
def shed(self):
self.defense=self.defense+1
def attack(self, opposite, current):
opposite.hp=opposite.hp-(current.attack-opposite.defense)
def eat(self):
self.attack=self.attack+5
print(str(self.name) + " eats a rat!")
print(str(self.name) + "'s attack dmg is now " + str(self.attack))
def sleep(self):
print (str(self.name) + " goes to sleep")
self.hp=self.hp+10
if self.hp>100:
self.hp=100
print (str(self.name) + " wakes up with " + str(self.hp) + "hp")
##initialises the snakes
alpha=Snake()
beta=Snake()
## gives the snakes names of the user's choice
alpha_name=raw_input("What would you like to name your snake? ")
alpha.set_name(alpha_name)
beta_name=raw_input("What would you like to name the other snake? ")
beta.set_name(beta_name)
##starts the game
turn=True
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite="beta"
current="alpha"
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(opposite, current)
if action=="sleep":
alpha.sleep()
if action=="eat":
alpha.eat()
if action=="shed":
alpha.shed()
turn=False
except IOError:
print("Please chose only one action, exaclty how it is typed")
while turn==False:
opposite="alpha"
current="beta"
if beta.hp<15:
beta.sleep()
elif alpha.hp>75:
beta.attack()
else:
index=random.randint(1, 3)
if index==1:
beta.shed()
elif index==2:
beta.eat()
else:
beta.attack(opposite, current)
turn=True
in "attack" you try to access "opposite.hp", but this method is called with a string instead of an object:
opposite="alpha"
current="beta"
=> change this to
opposite=alpha
current=beta
also, there is a field and a method with the same name in the class: attack. I suggest renaming the field to "attackpoints" or something.
additionaly, you call "beta.attack()". you forgot the method arguments there.
I see two problems. The first is you're passing the name of the variable instead of the variable itself.
change this:
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite="beta"
current="alpha"
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(opposite, current)
to this:
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite=beta
current=alpha
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(opposite, current)
Additionally, you have the attack field defined twice in the Snake class.
class Snake:
attack=25
def attack(self, opposite, current):
Here's what I came up with after playing with your code:
import random
class Snake:
hp=100
attack_skill=25
defense=1
def set_name(self, name):
self.name=name
def shed(self):
self.defense=self.defense+1
def attack(self, opposite):
opposite.hp = opposite.hp - (self.attack_skill - opposite.defense)
def eat(self):
self.attack_skill += 5
print(str(self.name) + " eats a rat!")
print(str(self.name) + "'s attack dmg is now " + str(self.attack_skill))
def sleep(self):
print (str(self.name) + " goes to sleep")
self.hp=self.hp+10
if self.hp>100:
self.hp=100
print (str(self.name) + " wakes up with " + str(self.hp) + "hp")
##initialises the snakes
alpha=Snake()
beta=Snake()
## gives the snakes names of the user's choice
alpha_name=raw_input("What would you like to name your snake? ")
alpha.set_name(alpha_name)
beta_name=raw_input("What would you like to name the other snake? ")
beta.set_name(beta_name)
##starts the game
turn=True
while alpha.hp>0 and beta.hp>0:
while turn==True:
opposite="beta"
current="alpha"
action=raw_input("attack, sleep, eat or shed? ")
try:
if action=="attack":
alpha.attack(beta)
if action=="sleep":
alpha.sleep()
if action=="eat":
alpha.eat()
if action=="shed":
alpha.shed()
turn=False
except IOError:
print("Please chose only one action, exaclty how it is typed")
while turn==False:
opposite="alpha"
current="beta"
if beta.hp<15:
beta.sleep()
elif alpha.hp>75:
beta.attack(alpha)
else:
index=random.randint(1, 3)
if index==1:
beta.shed()
elif index==2:
beta.eat()
else:
beta.attack(alpha)
turn=True
When you beta attack, you are calling the attack() method without any parameters. I assume you want beta.attack(alpha,beta)
But you could probably refactor the method to only require the opponent as a parameter (since you know who is attacking (it's the object calling the attack method))
def attack(self, opposite):
opposite.hp -= self.attack-opposite.defense