I am having trouble getting my Python program to work for my class assignment. I have written what I think is the correct code but I still get errors like:
*NameError: name 'self' is not defined* Here is the Assignment:
Create a final program that meets the requirements outlined below.
Create an automobile class that will be used by a dealership as a vehicle inventory program. The following attributes should be present in your automobile class:
private string make
private string model
private string color
private int year
private int mileage
Your program should have appropriate methods such as:
constructor
add a new vehicle
remove a vehicle
update vehicle attributes
At the end of your program, it should allow the user to output all vehicle inventory to a text file.
Below is my code and any help is appreciated:
class Automobile:
def __init__(self, make, model, color, year, mileage):
self.make = make
self.model = model
self.color = color
self.year = year
self.mileage = mileage
def add_vehicle(self):
auto = Automobile()
vehicle_file = open('vehicle.txt', 'a')
make = input("Enter make: ")
model = input("Enter model: ")
color = input("Enter color: ")
year = input("Enter year: ")
mileage = input("Enter mileage: ")
vehicles = Automobile(make, model, color, year, mileage)
vehicle_list = [vehicles.make, vehicles.model, vehicles.color, vehicles.year, vehicles.mileage]
for i in vehicle_list:
vehicle_file.write("%s\t" % item)
vehicle_file.write("\n")
vehicle_file.close()
print("Your record has been succesfully added to the inventory")
def delete_vehicle(self):
del_rec = input("Enter record to delete: ")
with open("vehicle.txt","r+") as f:
new_f = f.readlines()
f.seek(0)
for line in new_f:
if del_rec not in line:
f.write(line)
f.truncate()
print("Succesfully deleted record from inventory")
def set_make(self, make):
self.make = make
def get_make(self):
return self.make
def set_model(self, model):
self.model = model
def get_model(self):
return self.model
def set_color(self, color):
self.color = color
def get_color(self):
return self.color
def set_year(self, year):
self.year = year
def get_year(self):
return self.year
def set_mileage(self, mileage):
self.mileage = mileage
def get_mileage(self):
return self.mileage
def main():
menu = {}
menu['1']="Add Vehicle."
menu['2']="Delete Vehicle."
menu['3']="Find Vehicle"
menu['4']="Exit"
user=True
while user:
print ("""
1.Add a Vehicle
2.Delete a Vehicle
3.View Inventory
4.Exit/Quit
""")
ans=input("What would you like to do? ")
if ans=="1":
Automobile.add_vehicle
elif ans=="2":
Automobile.delete_vehicle(self)
elif ans=="3":
print(Automobile.vehicles)
elif ans=="4":
print("\n Goodbye")
break
elif ans !="":
print("\n Invaild Entry")
if __name__ == "__main__":
main()
Assuming you are importing this module you have created and using it in main, it works fine for me. The only thing you need to change is to change i to item in your for loop, and remove the self in delete vehicle all the way at the bottom. This removed all of the errors for me from your class. Also Please do note that if you are supposed to be using private and protected variables you need to add for ex: __self.Make. Your variables are currently not private or protected. by adding the _ or __ modifier you make the variables private or protected. I'm guessing you have a vague idea of what private and protected do, but that's why you need the getter and setters. give that a shot and see if it helps! also if you are still unclear please make sure to look back over private and protected variables. also not sure if your add vehicle method will work at the bottom because you didn't close the parentheses. it should be addvehicle()
Related
new to python , trying to learn oops ,
in below code my objective is to sort employee list based on rating but stuck at object not iteratable.
class Employee:
def getfn(self):
self.empid=(input(" enter emp id:"))
self.name=input("enter name:")
self.gender=input("enter emp gender: ")
self.salary=input(" enter emp salary:")
self.rating=int(input("enter rating:"))
empz=[]
class menu:
n=0
def entry(self):
n=int(input(" enter no of employees:"))
i=0
while i<n:
temp_emp=Employee()
temp_emp.getfn()
empz.append(temp_emp)
i+=1
def print_rec(self):
#
print("-id--name--gender--salary--rating--")
for i in empz:
print(i.empid,i.name,i.gender,i.salary,i.rating)
#print(sorted(empz,key=lambda x:x[4]))
def sort_rating(empz):
return empz.rating
sorted_emp=sorted(empz, key= sort_rating)
print(empz)
The design of your Employee class isn't great. Values used as its attributes should be validated before class construction.
You can control the number of employees to be input more easily than asking for a count.
Hopefully this will give a better idea of how this might be done.
class Employee:
def __init__(self, empid, name, gender, salary, rating):
self.empid = empid
self.name = name
self.gender = gender
self.salary = salary
self.rating = rating
def __str__(self):
return f'ID={self.empid}, Name={self.name}, Gender={self.gender}, Salary={self.salary}, Rating={self.rating}'
# common input functions
def getInput(prompt, t=str):
while True:
v = input(f'{prompt}: ')
try:
return t(v)
except ValueError:
print('Invalid input')
def getInt(prompt):
return getInput(prompt, int)
def getFloat(prompt):
return getInput(prompt, float)
# end of common input functions
employeeList = []
while eid := getInput('ID (Enter to finish)'):
name = getInput('Name')
gender = getInput('Gender')
salary = getFloat('Salary')
rating = getInt('Rating')
employeeList.append(Employee(eid, name, gender, salary, rating))
for employee in sorted(employeeList, key=lambda x: x.rating):
print(employee)
The common input functions should be in a separate py file so you can import them when needed rather than re-writing them every time. They're trivial but you'll find them helpful when trying to ensure that input is appropriate
I'm making a text-based adventure game in python and would like the user to choose a race and create an instance of a race class based on their choice. For example, if the player chose a Lizardman race from this code:
def character_creation():
print("You have four choices, choose wisely")
races = ['Lizard', 'Bookshelf', 'Genie', 'Werepus']
while True:
for i, j in enumerate(races):
print(f"[{i + 1}]", j)
choice = int(input('Pick a race:'))
if choice <= len(races):
print('You are a ', races[choice])
return races[choice]
else:
continue
How would I get my code to make a race object?
character = Race('Lizardman', 'Regrowth', 20)
Each race is created by Race(Name, Passive, HP) and each race has its own passive and hp associated with it. As in, I don't want to ask the user for the passive and the HP, just the race name.
You can use classmethod here.
class Race:
def __init__(name: str, passive: str, hp: int):
self.name = name
self.passive = passive
self.hp = hp
#classmethod
def from_race_name(cls, name):
race_attributes = {'Lizardman':{'passive': 'Regrowth',
'hp': 20,
.....}
return cls(name,
race_attributes[name]['passive'],
race_attributes[name]['hp'])
This will create an instance of the class based on only name of the race. To use it call it with the class name:
liz = Race.from_race_name('Lizardman')
This will create an instance of lizardman which will automatically be assigned 'regrowth' passive and 20 hp.
Also, if you want to create a 'unique' lizardman you can still do it manually:
admiral_akbar = Race(name='Lizardman', passive='panic', hp=999)
If you want the user to only choose the race name and have everything else on default you can set the default values in the class parameters.
Here's an example:
class Race():
def __init__(self, Name: str, Passive: str = "Regrowth", HP: int = 20): # Set default values here
self.Name = Name
self.Passive = Passive
self.HP = HP
def Main():
race_name = input("Pick a race: ")
character = Race(race_name)
print(character.Name, character.Passive, character.HP)
if __name__ == "__main__":
Main()
Output if user enters 'Lizardman':
Lizardman Regrowth 20
You can still overwrite and change the the Passive and the HP as so:
character = Race(Name = race_name, Passive = "Something", HP = 100)
I am making a text based adventure game in python. Once the game begins, I would like to create an instance of a class called "Character" which is the player's character object. I would like the user to be able to choose the race of the character they want to play. So far I have:
class Race:
def __init__(self, name, passive, hp):
self.name = name
self.passive = passive
self.hp = hp
and
class Lizard(Race):
def __init__(self, name, passive, hp):
super().__init__(name, passive, hp)
self.name = 'Lizardman'
self.passive = 'Regrowth'
self.hp = 20
def regrowth(self):
if 0 < self.hp <= 18:
self.hp += 2
and
def race_select():
races = ['Lizard']
while True:
for i, j in enumerate(races):
print(f"[{i + 1}]", j)
choice = int(input('Pick a race:'))
if choice <= len(races):
print('You are a ', races[choice - 1])
return races[choice - 1]
else:
continue
If I understand correctly, if I wanted the race to be a Lizard, I would still have to do
character = Lizard('Lizardman', 'Regrowth', 20)
Is there an easy way to let the user choose the race and the object to be created accordingly? Thanks
A simple solution would be to map a name to a class using a dictionary. As a simple example:
race_map = {"lizard": Lizard,
"human": Human} # I'm adding a theoretical other class as an example
choice = input('Pick a race:')
race_initializer = race_map.get(choice, None) # Get the chosen class, or None if input is bad
if race_initializer is None:
# They entered bad input that doesn't correspond to a race
else:
new_creature = race_initializer(their_name, their_passive, their_hp)
new_creature is now the new object of the chosen class.
You may want to standardize the input using choice.lower() to ensure that capitalization doesn't matter when they enter their choice.
I changed it to allow for specifying a race by a string name instead of a number. If you wanted a number, you could keep your list, but apply the same idea. Something like:
race_list = races = [('Lizard', Lizard), ('human', Human)]
choice = int(input('Pick a race:'))
try:
race_initializer = race_list[choice][1] # 1 because the class object is the second in the tuple
new_creature = race_initializer(their_name, their_passive, their_hp)
except IndexError:
# Bad input
I included the name in the race_list so that you can loop over the list and print out index->name associations for the user to pick from.
You may also want to use a more robust structure than a plain tuple to store name->initializer mappings, but it works well in simple cases.
I'm currently working on a text adventure in python (this language just because it's the one I know), and I'm finding that creating and loading savefiles removes some of the mecahnics I've made. I'll include the problematic code here, rather than all of elements that work fine. it's mainly to do with classes and how instances are 'pickled'.
Here are some of the classes I've created:
class Player:
def __init__(self, name):
self.sack = []
self.kit = []
self.equipped = []
self.log = []
self.done = []
class Weapon:
def __init__(self, name, price, minattack, maxattack):
self.name = name
self.price = price
self.minattack = minattack
self.maxattack = maxattack
class Food:
def __init__(self, name, price, healthadd):
self.name = name
self.price = price
self.healthadd = healthadd
class Quest:
def __init__(self, name, requirement, num, gold, npc, place, give_text, prog_text, comp_text, done_text):
self.name = name
self.requirement = requirement
self.num = num
self.score = 0
self.gold = gold
self.npc = npc
self.place = place
self.give_text = give_text
self.prog_text = prog_text
self.comp_text = comp_text
self.done_text = done_text
The instances in the Player class I've included here are just the ones that are appended by other mechanics with Weapons, Food and Quests. The code includes regions where Weapons, Food and Quests are populated (though working on a separate assets file might tidy things up a bit).
Here's how the save/load functions work currently:
def save(lastplace):
clear()
with open('savefile', 'wb') as f:
PlayerID.currentplace = lastplace.name
pickle.dump(PlayerID, f)
print("Game saved:\n")
print(PlayerID.name)
print("(Level %i)" % (PlayerID.level))
print(lastplace.name)
print('')
option = input(">>> ")
goto(lastplace)
def load():
clear()
if os.path.exists("savefile") == True:
with open('savefile', 'rb') as f:
global PlayerID
PlayerID = pickle.load(f)
savedplace = PlayerID.currentplace
savedplace = locations[savedplace]
goto(savedplace)
else:
print("You have no save file for this game.")
option = input('>>> ')
main()
It's worth noting that upon entry to the game, PlayerID (you) becomes a global variable. You might begin to see some of the issues here, or rather the overarching issue. Essentially, the pickling process serialises all of the possible class types stored in lists within the class of Player just get appended by their names, thus removing their class properties when loaded back into the game.
Is there a pythonic way to ensure that class instances are saved for a future load so that they can still behave as classes, particularly when stacked inside the class of Player? I appreciate this is more of an editorial rather than a question by its length, but any help would be hugely appreciated.
I Have this class:
class Bowler:
def __init__(self, name, score):
self.name = name
self.score = score
def nameScore(self):
return '{} {}'.format(self.name, self.score)
I need to get user input until a blank line is entered. Then use the data I got to create instances of a class. I was thinking something like:
def getData():
name, score = input("Please enter your credentails (Name score): ").split()
B1 = Bowler(name, score)
print(B1.nameScore())
But then I would somehow have to loop it until I get a blank user input. Also I would somehow have to create B2 B3 B4 etc in the loop.
Sorry I am still really new to programming, maybe I am looking at this from the wrong angle.
What you're looking for are Python Lists. With these you will be able to keep track of your newly created items while running the loop. To create a list we simply defined it like so:
our_bowlers = []
Now we need to alter our getData function to return either None or a new Bowler:
def getData():
# Get the input
our_input = input("Please enter your credentails (Name score): ").split()
# Check if it is empty
if our_input == '':
return None
# Otherwise, we split our data and create the Bowler
name, score = our_input.split()
return Bowler(name, score)
and then we can run a loop, check for a new Bowler and if we didn't get anything, we can print all the Bowlers we created:
# Get the first line and try create a Bowler
bowler = getData()
# We loop until we don't have a valid Bowler
while bowler is not None:
# Add the Bowler to our list and then try get the next one
our_bowlers.append(bowler)
bowler = getData()
# Print out all the collected Bowlers
for b in our_bowlers:
print(b.nameScore())
This is my code to do what you want:
class Bowler:
def __init__(self, name, score):
self.name = name
self.score = score
def nameScore(self):
return '{} {}'.format(self.name, self.score)
def getData():
try:
line = input("Please enter your credentails (Name score): ")
except SyntaxError as e:
return None
name, score = line.split()
score = int(score)
B = Bowler(name, score)
print(B.nameScore())
return B
if __name__ == '__main__':
bowlers = list()
while True:
B = getData()
if B == None:
break
bowlers.append(B)
for B in bowlers:
print(B.nameScore())
In addition, I recommend you to modify your input for it's inconvenient now