How to pass string as object name? - python

Here's how I finally solved the problem:
I created two lists, one containing the objects, the other containing the object names (strings). Then I write in the code to make sure that an object and its name are appended to the two lists at the same time. So that I can easily call an object with ObjectList[NameList.index(Name)], similarly with NameList[ObjectList.index(Object)] to call a name.
I don't know if it's the best solution. Maybe I'll find a better way to do this when I know more about python.
Thanks everyone for your help.
I've updated my code below.
I am trying to make a game that can take in user input, make new objects based on that input, and connect that object with an existing web of objects.
So I have the initial objects: Adam = Human("Male","God","God") and Eve = Human("Female", "God", "God")
But after Adam and Eve, I want to create objects like Josh = Human("Male", Adam, Eve), here the attributes of Josh becomes one string and two objects, instead of three strings. But if this worked, I can create a web of objects where every obect-child (except Adam and Eve) has object-parents.
If anyone has any suggestions on that, please let me know.
I want to pass an user-input string as the name of a new object of a certain class. I can't use eval() because it's dangerous. What can I do?
I am new to python3 and creating a little game just for practicing. I've created this class called "Human", and in the game users are supposed to input a name for a new Human.
I haven't tried much as none of the questions I found match my problem. I only know so far that I can't use eval() because it might cause trouble if things like eval("import") happened.
import random
# list of all humans
Humans = []
# creating the class Human
class Human:
global Humans
def __init__(self, gender, father, mother):
self.gender = gender
self.father = father
self.mother = mother
self.canHaveChild = False
Humans.append(self)
def growup(self):
self.canHaveChild = True
Adam = Human("Male", "God", "God")
Eve = Human("Female", "God", "God")
Humans.append(Adam)
Humans.append(Eve)
# creating the class SpiritualHuman
class SpiritualHuman:
def __init__(self, gend, stparent, ndparent):
self.stparent = stparent
self.ndparent = ndparent
self.gend = gend
self.canHaveChild = False
# haveChild function
def haveChild(Human1, Human2):
gender = ""
gen_pro = random.random()
if gen_pro < 0.5:
gender = "Female"
else:
gender = "Male"
if Human1.canHaveChild & Human2.canHavechild:
if (Human1.gender == "Male") & (Human2.gender == "Female"):
return Human(gender, Human1, Human2)
elif (Human1.gender == "Female") & (Human2.gender == "Male"):
return Human(gender, Human1, Human2)
elif (Human1.gender == "Male") & (Human2.gender == "Male"):
return SpiritualHuman("Yang", Human1, Human2)
else:
return SpiritualHuman("Yin", Human1, Human2)
else:
return "forbidden child"
# a list of all commands
command_list = ["who is the mother of", "who is the father of", "who is the child of", "have child named"]
# user input could be:
# "who is the mother of xxx"
# "who is the father of xxx"
# "who is the child of xxx and xxx"
# "xxx and xxx have child named xxx"
# user input function
def get_input():
command = input(":")
comsplit = command.split()
# check 1st command
if command_list[0] in command:
if comsplit[5] in str(Humans):
print("the mother of", comsplit[5], "is", Humans[str(Humans).index(comsplit[5])].mother())
else:
print(comsplit[5], "does not exist")
# check 2nd command
elif command_list[1] in command:
if comsplit[5] in str(Humans):
print("the father of", comsplit[5], "is", Humans[str(Humans).index(comsplit[5])].father())
else:
print(comsplit[5], "does not exist")
# check 3rd command
elif command_list[2] in command:
if comsplit[5] in str(Humans) and comsplit[7] in str(Humans):
for i in Humans:
if str(i.father()) in [comsplit[5], comsplit[7]] and str(i.mother()) in [comsplit[5], comsplit[7]]:
print(i, "is the child of", comsplit[5], "and", comsplit[7])
else:
print("they don't have a child")
else:
print("at least one of the parents you mentioned does not exist")
# check 4th command
elif command_list[3] in command:
if comsplit[0] in str(Humans) and comsplit[2] in str(Humans):
# here's where the problem is
# I want to use comsplit[7] as name for a new Human object
# how should I do it?
else:
print("at least one of them is not human")
elif command == "humans":
print(str(Humans))
else:
print("invalid command. If you need help, please type 'help'")
while(True):
get_input()
I don't know how to avoid errors, but I expect that if the user inputs:
Adam and Eve have child named Josh
the result should be that Josh is an object of class Human whose father is Adam and mother is Eve.

Use a dict containing your humans, with their names as keys:
# global dict, defined at the top of your code
humans = {}
def get_input():
command = input(":").split()
if len(command) == 1:
print(HUMANS) # well, don't know what this one is supposed to be...
elif len(command) > 1:
humans[command[1]] = Human(command[1])
humans[command[2]] = Human(command[2])
humans[command[0]] = haveChild(humans[command[1]], humans[command[2]])
Edit: I just read your comment, can't finish to answer right now, but in short, you must create your father and mother as humans before you can use them, so you need to change something in the way you create them...

The user will enter 2 humans objects with their attributes (gender,father,mother).The 2 objects will be passed to haveChild().Check my code
//import radom, it was missing from your code
import random
class Human:
def __init__(self, gender, father, mother):
self.gender = gender
self.father = father
self.mother = mother
self.canHaveChild = False
def growup(self):
self.canHaveChild = True
def haveChild(obj1, obj2):
gender = ""
gen_pro = random.random()
if gen_pro < 0.5:
gender = "Female"
else:
gender = "Male"
//obj1.canHaveChild & obj2.canHavechild, was throwing error
//'Human' object has no attribute 'canHavechild'
if obj1.canHaveChild and obj2.canHavechild:
if (obj1.gender == "Male") & (obj2.gender == "Female"):
return Human(gender, Human1, Human2)
elif (obj1.gender == "Female") & (obj2.gender == "Male"):
return Human(gender, mother, father)
elif (obj1.gender == "Male") & (obj2.gender == "Male"):
return SpiritualHuman("Yang", Human1, Human2)
else:
return SpiritualHuman("Yin", Human1, Human2)
else:
return "forbidden child"
def get_input():
print("Enter Human1 gender,father,mother")
command = input(":").split()
human1 = Human(command[0],command[1],command[2])
print("Enter Human2 gender,father,mother")
command = input(":").split()
human2 = Human(command[0],command[1],command[2])
haveChild(human1,human2)
# the problem above is, command[0] is an immutable (a string), I can't use it
# directly as the name of a new object
get_input()

Related

How do I pass a return value in a function in a class to another function within the same class?

I'm working with and getting better at class objects and I started a new project that will check to see if the user is eligible for MIT or Harvard based on their GPA, SAT, and ACT scores (don't fact check me I thought this would just be a fun project and came up with the numbers off the top of my head)
I haven't started working on my Harvard Eligibility part of the project yet, so I'm only going to be using the MIT side.
This is my main file
#Inheritance
#8/28/2020
from mitstudent import mitstudent #This is importing both of the classes
from harvardstudent import harvardstudent
name = str(input("What is your name?: ")) #Asking the user's name to use as an argument for the parameter
while True: #This while loop using try and except to make sure that the user inputs a number instead of a string
try:
name = mitstudent()
except ValueError:
print("Input a number")
else:
break
print(mitstudent.eligible(name))
This is my mitstudent.py file that contains my class
#8/28/2020
#Inheritance
class mitstudent:
def __init__(self): #These are my class objects, the student will input their GPA, ACT score, and SAT score and the
#function will input it as the objects
self.gpa = float(input("What is your gpa?: "))
self.act = float(input("What is your ACT score?: "))
self.sat = float(input("What is your SAT score?: "))
'''
The next three class functions will be to check if the gpa, act, or sat scores are "eligible" for MIT if they are, the
function will return a value of "eligible" and if they aren't the function will return a value of "not eligible"
'''
def gpachecker(self):
if float(self.gpa) >= 3.5:
return "eligible"
else:
return "not eligible"
def actchecker(self):
if float(self.act) >= 33:
return "eligible"
else:
return "not eligible"
def satchecker(self):
if float(self.sat) >= 1400:
return "eligible"
else:
return "not eligible"
def eligible(self): #This function checks to see if the student has met all of the requirements to be eligible for
#Mit, which includes a gpa over 3.5, an act score over 33, and an sat score over 1400
if mitstudent.gpachecker and mitstudent.actchecker and mitstudent.satchecker == "eligible":
return "This student is eligible for MIT"
else:
return "This student is ineligible for MIT"
In the main file, I set a name and inputted 9999 for all of the objects, however it still says the student is ineligible.
I believe it is because the return statement within the gpachecker (act & sat aswell) function is not actually returning the way I want it to. Is there a way I can return the statement from those functions
def gpachecker(self):
if float(self.gpa) >= 3.5:
return "eligible"
else:
return "not eligible"
for it to actually be used in this if statement?
def eligible(self): #This function checks to see if the student has met all of the requirements to be eligible for
#Mit, which includes a gpa over 3.5, an act score over 33, and an sat score over 1400
if mitstudent.gpachecker and mitstudent.actchecker and mitstudent.satchecker == "eligible":
return "This student is eligible for MIT"
else:
return "This student is ineligible for MIT"
I think the problem lies in your if statement.
if mitstudent.gpachecker and mitstudent.actchecker and mitstudent.satchecker == "eligible":
The condition will be evaluated like this:
mitstudent.gpachecker and mitstudent.actchecker and (mitstudent.satchecker == "eligible")
First of all, if you want to get the value returned by the methods, you have to call it using self.method_name().
While the values for mitstudent.gpachecker, mitstudent.actchecker, and mitstudent.satchecker will always be True since they pertain to the methods of the class, (mitstudent.satchecker == "eligible") is always False given that mitstudent.satchecker is a function, not a string.
A solution would be something like:
if self.gpachecker() == "eligible" and self.actchecker() == "eligible" and self.satchecker() == "eligible":
You may also want to modify your checker methods to return Boolean(True or False) values instead of strings so that your condition would become shorter:
if self.gpachecker() and self.actchecker() and self.satchecker():

User input not saving into inventory list

Basically I am making an app to better assist me at managing my ebay store. I am still very new to programming and OOP. After watching some tutorials I pieced together the following code. Everything so far works pretty well. What I am currently stuck on is when the user inputs an item for inventory, it is not saving it. And, when the user wants to view the inventory the item they added wont populate. Any input or suggestions would be much apprenticed.
def Inventory():
All_Inventory = {}
class Ebay_Inventory:
def __init__(self, manufacturer, object_type, price):
self.manufacturer = manufacturer
self.object_type = object_type
self.price = price
def add_item(self):
manufacturer = input("Enter Manufacturer: ")
object_type = input("Enter what the item is: ")
price = input("Enter price: ")
item_info = Ebay_Inventory(manufacturer, object_type, price)
All_Inventory = item_info
print("Item added successfully")
def delete_item(self):
delete = input("What is the item you want to delete?: ")
if delete in All_Inventory.keys():
del[delete]
print("The item entered has been deleted.")
else:
print("Item not found")
def sale_status(self):
update = input("What is the item you want to update?:")
if update in All_Inventory.keys():
pass
else:
print("Item not found")
user=True
while user:
print("\n1. Add to item inventory")
print("2. Remove item from inventory")
print("3. Update sale status")
print("4. View inventory")
print("5. Exit program")
user_wants=input("What would you like to do today?")
if user_wants=="1":
Ebay_Inventory.add_item(input)
elif user_wants=="2":
Ebay_Inventory.delete_item(input)
elif user_wants=="3":
Ebay_Inventory.sale_status(input)
elif user_wants=="4":
print(All_Inventory)
elif user_wants=="5":
print("\n Thank you for using item inventory.")
break
elif user_wants!="":
print("\n Input not understood. Please try again.")
You need to read about Scope, OOP and dicts:
You are not adding to your Inventory.All_Inventory - you create a new local with All_Inventory = item_info
https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces
Short description of the scoping rules?
You mix up static class attributes and instance attributes, read:
https://docs.python.org/3/tutorial/classes.html#class-objects.
What is the difference between #staticmethod and #classmethod?
You are deleting / accessing your dictionary wrongly - see :
https://docs.python.org/3/tutorial/datastructures.html#dictionaries
Delete an element from a dictionary
Fixed:
class Ebay_Inventory:
Inventory = {} # class property
#staticmethod
def print_inventory():
for k in Ebay_Inventory.Inventory:
for i in Ebay_Inventory.Inventory[k]:
print(k,i)
class Ebay_Item:
def __init__(self, key, manufacturer, object_type, price):
self.manufacturer = manufacturer
self.object_type = object_type
self.price = price
self.key = key
def __str__(self):
return f"{self.manufacturer} {self.object_type} {self.price}"
def __repr__(self):
return str(self)
#staticmethod
def add_item(key=None, man=None, obj=None, pri=None):
# use values if given, else ask - this is for demo purposes only
key = key or input("Enter key: ")
manufacturer = man or input("Enter Manufacturer: ")
object_type = obj or input("Enter what the item is: ")
price = pri or input("Enter price: ")
# create new item
item_info = Ebay_Inventory.Ebay_Item(key, manufacturer, object_type, price)
# add to class member, create key if need be
Ebay_Inventory.Inventory.setdefault(item_info.key,[]).append(item_info)
def delete_item(key=None):
delete = key or input("What is the item you want to delete?: ")
if delete in Ebay_Inventory.Inventory:
del Ebay_Inventory.Inventory[delete]
print("The item entered has been deleted.")
else:
print("Item not found")
def __str__(self):
return Ebay_Inventory.print_inventory()
# add 2 items and print
Ebay_Inventory.add_item(1,"Me","Me",1000)
Ebay_Inventory.add_item(2,"You","You",1000)
Ebay_Inventory.print_inventory()
# remove non existent and existent item and print
Ebay_Inventory.delete_item(3)
Ebay_Inventory.delete_item(2)
Ebay_Inventory.print_inventory()
Output:
1 Me Me 1000
2 You You 1000
Item not found
The item entered has been deleted.
1 Me Me 1000
Sorry to rework your code pretty extensively, but I think this is more like what you are going for:
class EbayInventory:
def __init__(self):
self.all_inventory = []
def print_items(self):
print('Current item list by index:')
for i in range(0, len(self.all_inventory)):
print("{} -> {}".format(i+1, self.all_inventory[i]))
def add_item(self):
manufacturer = input("Enter Manufacturer: ")
object_type = input("Enter what the item is: ")
price = input("Enter price: ")
item = {'manufacturer': manufacturer, 'type': object_type, 'price': price}
self.all_inventory.append(item)
print("Item added successfully")
def delete_item(self):
self.print_items()
delete = int(input("Item id you want to delete: "))
try:
del self.all_inventory[delete - 1]
print("The item entered has been deleted.")
except Exception as e:
print("An error occurred deleting that item, details below")
print(e)
def sale_status(self):
self.print_items()
update_index = int(input("Item id you want to update: "))
if update_index > len(self.all_inventory) or update_index <= 0:
print("You're trying to change an item that doesn't exist!!")
return
print("OK. Let's get that item up to date!")
manufacturer = input("Enter Manufacturer: ")
object_type = input("Enter what the item is: ")
price = input("Enter price: ")
item = {'manufacturer': manufacturer, 'type': object_type, 'price': price}
self.all_inventory[update_index - 1] = item
print("OK. We got that update taken care of")
if __name__ == "__main__":
my_app = EbayInventory()
while True:
print("\n1. Add to item inventory")
print("2. Remove item from inventory")
print("3. Update sale status")
print("4. View inventory")
print("5. Exit program")
user_wants = input("Please enter the number corresponding to how you would like help: ")
if user_wants == "1":
my_app.add_item()
elif user_wants == "2":
my_app.delete_item()
elif user_wants == "3":
my_app.sale_status()
elif user_wants == "4":
my_app.print_items()
elif user_wants == "5":
print("Thank you for using item inventory.")
break
else:
print("Input not understood. Please try again.")
You had a variable user that did nothing. You can simply enter an infinite loop with while True:. If you wanted to loop the way you did, then instead of a break you could have put a user = False to break out of the loop. This is sometimes a nifty trick, but doesn't make sense here I think. It seemed to me the inventory was really the only thing that would benefit by being stored in your class, and the methods could then access it to adjust it via a self.all_inventory. I moved your code to ask for item inputs to the add_item() and sale_status() methods, so now the main block of code looks a lot cleaner. I also wrapped it in if __name__ == "__main__": so that you can import this class to another project without running the entire program! I threw in some basic error checking with try: and except: clauses also. I think you were misunderstanding the difference between a Class and an Instance. So in my code the Class is EbayInventory, but the Instance is my_app. You create instances of your class just like I did with my_app = EbayInventory() and then the self now refers to my_app. In this manner I can call my_app.add_item(). You can have several instances of objects though, and they each have their own space in your computers memory. So you could have said:
app1 = EbayInventory()
app2 = EbayInventory()
app1.add_item()
And only the app1 will have any items, whereas app2 is still an empty list, but still has the methods to build an inventory via app2.add_item(). To answer your main question though, you never call your function Inventory() and therefore it doesn't exist to hold your information. When you call item_info = Ebay_Inventory(manufacturer, object_type, price) in fact you are making an Instance of a class, which is really nonsensical to do here because that means on the next line you could say item_info.add_item() and this would make another instance, yet you are not saving this information anywhere so you can never retrieve it!

How to compare 2 objects from a class

I have created a class called Dog_card. With this, I created player_card and computer_card. I am trying to compare the same attribute from both of these objects. There are more values to each than friendliness, but I have removed them so it is easier to test. I keep getting the error:
NameError: name 'player_card' is not defined
Here is my code:
class Dog_card:
def __init__(self):
self.name = ""
self.friendliness = ""
def printing_card(self):
prnt_str = "Name: %s \nIntelligence: %s" %(self.name, self.friendliness)
return prnt_str
def printing_player_card():
player_card = Dog_card()
player_card.name = dogs_list_player[0]
player_card.friendliness = random.randint(1,101)
def printing_computer_card():
computer_card = Dog_card()
computer_card.name = dogs_list_computer[0]
def choose_category():
user_choice_category = input("Please choose a category: ")
if user_choice_category not in ["1", "2", "3", "4"]:
print("Please choose from the options above")
choose_category()
else:
if user_choice_category == "1":
if player_card.friendliness > computer_card.friendliness:
print("Player has won the round!")
elif player_card.friendliness == computer_card.friendliness:
print("It is a Draw!")
Any help would be appreciated
The problem is as it's stated in the error. Basically you are trying to use player_card when it is not defined inside the definition of choose_category(). I suggest you pass the value of player_card to the function like the following
def choose_category(player_card):
or you can define it as an attribute so that it can be accessed by the methods of the same class.
you need to initialize play_card before using it. Maybe you call printing_player_card in order to intnialize before, but as you don't return anything from that function, the created object and the variable player_card only lives in scope of the function. When that function finished, player_card object variable is unknown and the object is destroyed.
if you want player_card (as well as computer_card) survice its function, you need to return it an save it to a variable outside the function code.
Furthermore your function name "printing" is bad, as you don't print anything. You just initialize your object.
Maybe that's what you are aiming at.
class Dog_card:
def __init__(self, name, friendliness=1):
self.name = name
self.friendliness = friendliness
def __str__(self):
return "Name: %s \nIntelligence: %s" %(self.name, self.friendliness)
player_card = Dog_card(dogs_list_player[0], random.randint(1,101))
computer_card = Dog_card(dogs_list_copmuter[0])
def choose_category():
user_choice_category = input("Please choose a category: ")
if user_choice_category not in ["1", "2", "3", "4"]:
print("Please choose from the options above")
choose_category()
else:
if user_choice_category == "1":
if player_card.friendliness > computer_card.friendliness:
print("Player has won the round!")
elif player_card.friendliness == computer_card.friendliness:
print("It is a Draw!")

Why is the module not callable

I have most of my program done however I keep getting the error and can't seem to figure out why it keeps doing so. I've also tried animal_list = Zoo.Zoo()
line 43, in addAnimal
animal_list = Zoo()
TypeError: 'module' object is not callable
here is some of my program
import Animal
import Zoo
def main():
#set user choice
choice = 0
while choice != "3":
display_menu()
#get user's choice
choice = str(input("What would you like to do? "))
#Perform selected choice
if choice.isalpha():
print("Please enter a numeical value")
elif choice == "1":
addAnimal()
and
#Add animal to list
def addAnimal():
atype = input("What type of animal would you like to create? ")
aname = input("What is the animal's name? ")
theAnimal = Animal.Animal(atype, aname)
theAnimal.set_animal_type(atype)
theAnimal.set_name(aname)
animal_list = Zoo()
animal_list.add_animal(theAnimal,Animal)
From looking at your other questions, your Zoo class is quite wrong.
Your Zoo class should be written like this:
class Zoo:
def __init__(self):
self.__animals = []
def add_animal(self, animals):
self.__animals.append(animal)
def show_animals(self):
size = len(self.__animals)
if size == 0:
print("There are no animals in your zoo!")
else:
return __animals
Instead you define methods like this:
def __init__(Animal):
and define variables like:
Animal.__animals = []
which simply don't make sense.
Your problem is that you used a module (Animal) instead of self. I have no idea where you might have gotten this idea, but you may want to peruse class definition in the Python documentation.

Problems transferring information from one part of a function to another

While working on my program I have run into a problem where the information stored in Menu option 1 is not being transferred to Menu option 2. As you can see it is correctly stored when in menu one. When it returns to go to menu option 2 its like it never went to option 1.
update #1:
some suggestions I've had is to understand scope? from what I can tell the program is not passing the data along to its parent program even though I've typed out return in each of the definitions.
#Must be able to store at least 4 grades
#Each class can have up to 6 tests and 8 hw's
#Weighted 40%*testavg 40% hw average attendance is 20%
#User must be able to input a minimum grade warning
#after each test the your program must calculate the students average and issue warning if necessary
##Define the Modules##
import math
def menu (a): #2nd thing to happen
menuend = 'a'
while menuend not in 'e':
menuend = raw_input("Type anything other then 'e' to continue:\n")
print "What would you like to do ?"
menudo = 0
print "1 - Enter Courses\n2 - Select Course to Edit\n3 - Save File\n4 - Load File\n5 - Exit\n"
menudo = input("Enter Selection:")
if (menudo == 1):
menuchck = 0
menuchck = raw_input("\nYou have entered #1 (y/n)?:\n")
if menuchck in ["Yes","yes","y","Y"]:
x = m1()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 2):
menuchck1 = 0
menuchck1 = raw_input("\nYou have entered #2 (y/n)?:\n")
if menuchck1 in ["Yes","yes","y","Y"]:
x = m2()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 3):
print "Entered 3"
elif (menudo == 4):
print "Entered 4"
else:
print "Anything Else Entered"
def course(): #3rd thing to happen
b = {}
while True:
while True:
print "\n",name,", please enter your courses below ('e' to end):"
coursename = raw_input("Course Name:")
if (coursename == 'e'):
break
will = None
while will not in ('y','n'):
will = raw_input('Ok for this name : %s ? (y/n)' % coursename)
if will=='y':
b[coursename] = {}
print "\n",name,", current course load:\n",b
coursechck = None
while coursechck not in ('y','n'):
coursechck = raw_input("Are your courses correct (y/n)")
if coursechck =='y':
return b
else:
b = {}
print
##Menu Options##
def m1():
a = course()
return a
def m2():
print "Excellent",name,"lets see what courses your enrolled in\n"
print x
return x
###User Input Section###
name = raw_input("Enter Students Name:\n")
a = {}
menu(a)
raw_input("This is the end, my only friend the end")
In your if-elif blocks in the do==1 case, you write m1(), but for the last case, you write x=m1(). You should have the latter everywhere (by typing m1() you only run the function, but do not store the returned x anywhere).
By the way, you can avoid this if-elif confusion using if chck in ["Yes","yes","Y","y"]:

Categories