Unable to access parent class' global variable with Child class' object - python-3.x

I want to update the counter of available cars whenever someone rents the car. When I try to access this variable through child class, it shows an error as "UnboundLocalError: local variable 'available_cars' referenced before assignment"
PS: Still working on it, that's why I haven't completed all the method codes.
Parent Class
available_cars = 1000
class Car_rental():
def __init__(self):
pass
def display_available_cars(self):
print("Total avaialable cars for renting is:", available_cars)
def rent_hourly(self, cars_rented):
print("Our hourly rate is $100/hr.")
if cars_rented > available_cars:
print("Sorry! We currently do not have the number of cars requested. You can have {} cars for now if you want.".format(
available_cars))
elif cars_rented < available_cars:
print("Thank you for renting {} cars from Swift car renting portal. Enjoy you ride.".format(
cars_rented))
elif cars_rented < 0:
print ("Please provide a valid number of cars.")
def rent_weekly(self):
pass
def rent_monthly(self):
pass
def bill(self):
pass
def update_invetory(self, cars_rented):
available_cars = available_cars - cars_rented
Child Class
from carRental import *
class Customer(Car_rental):
def init(self):
Car_rental.init(self)
def rent_cars(self):
mode = int(input(
"Please select the mode of renting the car:\n1. Hourly\n2. Weekly\n3. Monthly\n"))
if mode == 1 or mode == 'hourly' or mode == 'Hourly':
cars_rented = int(input("How many cars do you wish to rent?"))
self.rent_hourly(cars_rented)
self.update_invetory(cars_rented)
elif mode == 2 or mode == 'weekly' or mode == 'Weekly':
self.rent_weekly()
elif mode == 3 or mode == 'monthly' or mode == 'Monthly':
self.rent_monthly()
else:
print("Please provide appropriate input.")
def return_cars(self):
pass

So if I follow your question correctly, you seem to have objectives with your code.
You want to define a Car_Rental class with a class-level variable available_cars which is initially set to 1000, and then as customers rent vehicles decrement the number of available cars.
You also want a second Customer class which inherits the Car_Rental class which implements the billing functionality.
While I am unsure of this, it seems that you would also like each of these class definitions to reside in their own separate python script file.
This is how I would address these issues.
# If desired could be placed in separate file Car_Rental.py
class Car_Rental():
available_cars = 1000
def display_available_cars(self):
print("Total avaialable cars for renting is:", Car_Rental.available_cars)
def isOkayToRent(self, nmbr):
return nmbr <= Car_Rental.available_cars
def rent_hourly(self, cars_rented):
print("Our hourly rate is $100/hr.")
if cars_rented < 0:
print ("Please provide a valid number of cars.")
else:
if self.isOkayToRent(cars_rented):
print("Thank you for renting {} cars from Swift car renting portal. Enjoy you ride.".format(
cars_rented))
else:
print("Sorry! We currently do not have the number of cars requested. You can have {} cars for now if you want.".format(
Car_Rental.available_cars))
def rent_weekly(self):
pass
def rent_monthly(self):
pass
def bill(self):
pass
def update_inventory(self, nmbr):
assert nmbr > 0
Car_Rental.available_cars -= nmbr
#property
def cars(self):
return Car_Rental.available_cars
# Can be placed in second file.
#Note include this next line if classes are stored in separate files
#from Car_rental import Car_Rental
class Customer(Car_Rental):
def __init__(self):
Car_Rental.__init__(self)
def rent_cars(self):
mode = int(input(
"Please select the mode of renting the car:\n1. Hourly\n2. Weekly\n3. Monthly\n"))
if mode == 1:
cars_rented = int(input("How many cars do you wish to rent?"))
self.rent_hourly(cars_rented)
self.update_inventory(cars_rented)
elif mode == 2:
self.rent_weekly()
elif mode == 3:
self.rent_monthly()
else:
print("Please provide appropriate input.")
def return_cars(self):
pass
To use:
c1 = Customer()
c1.cars
1000
c1.rent_cars()
Please select the mode of renting the car:
1. Hourly
2. Weekly
3. Monthly
How many cars do you wish to rent? 2
Our hourly rate is $100/hr.
Thank you for renting 2 cars from Swift car renting portal. Enjoy you ride.
To illustrate proper inventory reduction:
c1.cars yields 998

Related

function without printing none

for some reason I'm printing two Nones, can someone explain how to avoid that?
class Wizard():
def __init__(self,name, gender,power):
self.name = name
self.gender = gender
self.power = power
def fire(self):
print('My power is the fire')
def wind(self):
print ('My power is the wind')
def power_wizard(self):
if power == 1:
print(Wizard.fire(self))
else:
a=print(Wizard.wind(self))
# Create player
name = input('Enter your wizard name: ')
gender = input ('Enter the gender: ')
power = int(input ('Choose your power 1) Fire and 2) Wind:(only numbers)'))
player1 = Wizard(name,gender,power)
print(player1.name)
print(power_wizard(power))
print (The question is how can I not print None or why am I printing None)
My power is the fire
None
None
And also why are 2 None where are the coming from, because when de function wizard_power there only to results.
why am I printing None
When you execute print(power_wizard(power)), the following happens:
the power_wizard() function is called.
in that power_wizard() function, you call the Wizard.fire() or Wizard.wind() methods...
in both methods, you print('My power is...')...
...but you don't return any result.
in the power_wizard() function, you print the result of the Wizard.fire() or Wizard.wind() methods but, as those methods returns nothing, None is printed a first time.
the power_wizard() function returns no results either...
...thus, the outermost print(power_wizard(power)) prints a second None.
That said, your Wizard class and power_wizard() function are a bit tangled...
You could easily remove the Wizard.fire() and Wizard.wind() methods and the power_wizard() function and have:
class Wizard():
def __init__(self, name, gender, power):
self.name = name
self.gender = gender
self.power = power
player1 = Wizard("Gandalf", "male", "fire")
player2 = Wizard("Hermione", "female", "wind")
player3 = Wizard("Draco", "male", "invisibility")
for p in (player1, player2, player3):
print("My name is %s and I have %s power" % (p.name, p.power))
# My name is Gandalf and I have fire power
# My name is Hermione and I have wind power
# My name is Draco and I have invisibility power
If you want to restrict the list of Wizard powers:
class Wizard():
powers = ("fire", "wind") # this is a _class variable_ defining
# all powers available to Wizards
def __init__(self, name, gender, power):
self.name = name
self.gender = gender
if power in Wizard.powers:
self.power = power
else:
raise ValueError("%s is not a Wizard power." % (power))
player3 = Wizard("Draco", "male", "invisibility")
# ValueError: invisibility is not a Wizard power.
If you want to let wizards describe themselves:
class Wizard():
...
def __init__(self, name, gender, power):
...
def __repr__(self):
return "<% is a %s with %s power>" % (
self.name, self.__class__.__name__, self.power)
for p in (player1, player2):
print(p)
# <Gandalf is a Wizard with fire power>
# <Hermione is a Wizard with wind power>
Then, if you want to make a wizard interactively:
def make_wizard():
while True:
name = input("Enter your wizard name: ")
if name:
break
gender = input("Enter its gender: ")
choices = ", ".join(Wizard.powers)
while True:
power = input("Enter its power (%s): " % (choices))
if power in Wizard.powers:
break
return Wizard(name, gender, power)
player1 = make_wizard()
print(player1)
# Enter your wizard name:
# Enter your wizard name: Gandalf
# Enter its gender: male
# Enter its power (fire, wind): invisibility
# Enter its power (fire, wind): fire
#
# <Gandalf is a Wizard with fire power>
If you want powers to be numbered choices:
def make_wizard():
...
choices = ", ".join("%i: %s" % (i, name)
for i, name
in enumerate(Wizard.powers, start=1))
while True:
try:
choice = int(input("Enter its power (%s): " % (choices)))
# will raise ValueError if choice is not a int
power = Wizard.powers[choice-1]
# will raise IndexError if choice-1 is not
# in Wizard.powers range
except ValueError, IndexError:
continue
else:
break
return Wizard(name, gender, power)
player1 = make_wizard()
print(player1)
# Enter your wizard name:
# Enter your wizard name: Gandalf
# Enter its gender: male
# Enter its power (1: fire, 2: wind): invisibility
# Enter its power (1: fire, 2: wind): 3
# Enter its power (1: fire, 2: wind): 1
#
# <Gandalf is a Wizard with fire power>
(that was fun... ;-)
You can only run the print statement if its return is not None like this. Its a bandaid fix.
if player1.name is not None: print(player1.name)

AttributeError: 'ElectricCar' object has no attribute 'battery_size'

i am learning from the book' "Python crash course a handbook". i have written the code exactly as it is in book but still i m getting error. can you please tell me what is the problem with below code:
i m getting 'AttributeError: 'ElectricCar' object has no attribute 'battery_size''.
class Car:
def __init__(self, make, model, year):
self.make=make
self.model=model
self.year=year
self.odometer_reading = 0
def get_discriptive_name(self):
long_name= f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""Print a statement showing the car's mileage."""
print(f"This car has {self.odometer_reading} miles on it.")
def update_odometer(self, mileage):
"""
Set the Odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self,miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
"""Inheritance from parent/superclass to child/subclass."""
class ElectricCar(Car):
"""Represent aspects of a car, specific to electric vehicles."""
def __intit__(self,make,model,year):
super().__init__(make,model,year)
self.battery_size = 75
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")
my_tesla = ElectricCar('tesla','model s', 2009)
print(my_tesla.get_discriptive_name())
my_tesla.describe_battery()
class ElectricCar(Car):
def __intit__(self,make,model,year):
super().__init__(make,model,year)
self.battery_size = 75
def describe_battery(self):
"""Print a statement describing the battery size."""
print(f"This car has a {self.battery_size}-kWh battery.")
if you take a look you misspelled the init function

Sorting a dictionary that contains a class holding 5 variable by one of the class variables

I have a dictionary that contains keys that are made from a class containing 5 variables. I want to sort this dictionary by one of the class vars.
here is what i currently have
class Player:
def __init__(self,name,wins,losses,ties,winpercent):
self.__name = name
self.__wins = wins
self.__losses = losses
self.__ties = ties
self.__winpercent = winpercent
# mutators
def setname(self,name):
self.__name = name
def setwins(self,wins):
self.__wins = wins
def setlosses(self,losses):
self.__losses = losses
def setties(self,ties):
self.__ties = ties
def setwinpercent(self,winpercent):
self.__winpercent = winpercent
# accessors
def getname(self):
return self.__name
def getwins(self):
return self.__wins
def getlosses(self):
return self.__losses
def getties(self):
return self.__ties
def getwinpercent(self):
return self.__winpercent
def displayHighScores(self):
print("\n"," "*2,self.__name," "*(24-len(self.__name)),self.__wins)
def displayplayers(self):
print(self.__name)
I store Players like this:
def addplayer(players):
newName = input("\nEnter new Player name or 9 to quit: ")
wins = "0"
losses = "0"
ties = "0"
winpercent = "0"
if not newName:
print("\nNo name detected try again")
addplayer(players)
elif newName == '9':
print("\nReturning to Options menu")
else:
players[newName] = Player(newName,wins,losses,ties,winpercent)
saveData(players)
return players
Finally i am working on a sorted hi scores list. right now i can print my dictionary unsorted like this:
def printhiscores(players):
print("\n"," "*13,"HiScores")
print(" "*3,"Name"," "*20,"Wins")
if len(players) == 0:
print("\nNo current Players in memory.")
else:
for x in players.keys():
players[x].displayHighScores()
DisplayHighScores () being a part of the class object.
I have been reading on dictionary sorting using
OrderedDict(sorted(players.items(), key=itemgetter(1)))
but this returns edit:TypeError: '<' not supported between instances of 'Player' and 'Player'
Again I am looking to sort my dictionary of players by their win attribute and then print this new order to a high score screen. Any help would be greatly appreciated. I will post if i make any more progress on my own on this.
Your Player instances are not orderable however, as they don't implement comparison methods:
TypeError: '<' not supported between instances of 'Player' and 'Player'
If you wanted to sort them by the value returned, say, wins, then just access that information instead of just returning the value:
OrderedDict(sorted(players.items(), key=lambda kv: kv[1].getwins()))
Otherwise, give your Player class rich comparison methods; methods by which to determine when one instance should be sorted before or after another. You'll also need an equality test. It's easier to just implement support for < (lower then) and equality, then use the #functools.total_ordering decorator to provide the rest:
from functools import total_ordering
#total_ordering
class Player:
def __lt__(self, other):
if not isinstance(other, Player):
return NotImplemented
return self.__wins < other.__wins
def __eq__(self, other):
if not isinstance(other, Player):
return NotImplemented
return self.__wins == other.__wins
The above makes two Player instances equal when their wins are equal, and orders them by that attribute. You'll need to adjust this for your application as needed.

Need help understanding why my code doesn't run [python]

So my goal is to make an ordering system for a cafe with various types of coffee available. Right now I'm having trouble understanding why my code doesn't run, whenever I execute the code nothing happens and I'm not sure why
class Coffee(object):
def __init__(self,name):
self.name = name
def coffee (self, coffee_type, price):
self.coffee_type = coffee_type
self.price = price
class Order(object):
def __init__(self, name):
self.name = name
def newOrder (self, coffee_type, coffee_amount):
this.coffee_type = coffee_type
this.coffee_amount = coffee_amount
class Main(object):
def __init__ (self, name):
self.name = name
from Coffee import coffee
flat_white = coffee("1 : Flat White", 3.50)
long_black = coffee("2 : Long Black", 3.50)
cappuccino = coffee("3 : Cappuccino", 4.00)
espresso = coffee("4 : Espresso", 3.25)
latte = coffee("5 : Latte", 3.50)
Ordering = 'Y'
while Ordering == 'Y':
try:
order_coffee = int(input("What coffee would you like to order?", pprint (vars(coffee))))
break
except:
ValueError
print ("wrong input")
order_amount = input("How many would you like to order?")
if order_coffee == 1:
new_Order(flat_white, order_amount)
elif order_coffee == 2:
new_Order(long_black, order_amount)
elif order_coffee == 3:
new_Order(cappuccino, order_amount)
elif order_coffee == 4:
new_Order(espresso, order_amount)
elif order_coffee == 5:
new_Order(latte, order_amount)
else:
print ("Please enter a valid number")
break
It looks like there are several issues with your code. I will try to help you out with a couple.
First, no need for the __init__ method to accept a name. Just make the method accept the necessary information for the object:
class Coffee(object):
def __init__ (self, coffee_type, price):
self.coffee_type = coffee_type
self.price = price
class Order(object):
def __init__(self, coffee_type, coffee_amount):
self.coffee_type = coffee_type
self.coffee_amount = coffee_amount
Second, since it does not really do anything, you can replace the Main class to an execution in a conditional as is typically seen in Python programs/scripts:
if __name__ =="__main__":
... # put main code here
Next, the except as it is written will catch all exceptions making debugging more difficult. If you only want to catch the ValueError, do:
except ValueError:
print ("wrong input")
If you use the current flow (i.e. with the try except block, you should put all of the order logic within the try block as it does not make any sense outside. Also, the necessary variables needed (order_coffee) will not be defined if you have a ValueError.
Adding a break after accepting the order input will cause you to break out of the ordering loop after an order is entered. This is probably not intended behavior. No break is needed here. Ditto for after outputting "Please enter a valid number".
When creating an Order, you just need to call Order(coffee_type, coffee_amount). When you create this order, make sure to set it to a variable too. probably something like:
new_order = Order(flat_white, order_amount)
Printing "Please enter a valid number" and "wrong input" is slightly redundant. You only need one of them to print under invalid input.
Lastly, pprint will print stuff out then return None so print(..., pprint(x)) will print an extra None once it has finished pretty printing x, instead just call pprint as if it was another call to print.
-- --
Making all of these changes, you will end up with something like:
class Coffee(object):
def __init__ (self, coffee_type, price):
self.coffee_type = coffee_type
self.price = price
class Order(object):
def __init__(self, coffee_type, coffee_amount):
self.coffee_type = coffee_type
self.coffee_amount = coffee_amount
if __name__ =="__main__":
coffee_available=[Coffee("1 : Flat White", 3.50),
Coffee("2 : Long Black", 3.50),
Coffee("3 : Cappuccino", 4.00),
Coffee("4 : Espresso", 3.25),
Coffee("5 : Latte", 3.50)]
ordering = 'Y'
while ordering == 'Y':
print("Coffee Type\t\tPrice")
print("-----------\t\t-----")
for coffee in coffee_available:
print("{}\t- - -\t$ {}".format(coffee.coffee_type,coffee.price))
print()
order_coffee = int(input("What is the number of the coffee you want? "))
order_amount = input("How many would you like to order? ")
new_order = None
if order_coffee >= 1 and order_coffee <=5:
new_order = Order(coffee_available[order_coffee-1], order_amount)
else:
print ("Please enter a valid number")

Python - Get a function to overwrite a variable

So I'm testing out some mechanics for a text-based game I was going to make. If the player has armour it would halve the damage they take and if not they would take full damage. The problem I'm having is that whenever I try to run the functions twice, it resets the health because it has been hardcoded. So I'm wondering how can I get the function to overwrite the health variable after it runs each time?
Here is the code:
import random
inventory = ["Armour","Sword","Healing Potion"]
health=100
def randDmg():
dealtDamage = random.randint(1,10)
print("You have taken "+str(dealtDamage)+" damage.")
return dealtDamage
def dmgCheck(damage, health):
if "Armour" in inventory:
damage = damage/2
else:
damage = damage
health-=damage
return health
print("Your new health is "+str(dmgCheck(randDmg(), health)))
Defining a global at the top of your dmgCheck function would work well - then you don't need to pass it in as a local. While you're at it, if you call the randDmg function within dmgCheck you won't need to pass that in either.
import random
inventory = ["Armour","Sword","Healing Potion"]
health=100
def randDmg():
dealtDamage = random.randint(1,10)
print("You have taken "+str(dealtDamage)+" damage.")
return dealtDamage
def dmgCheck():
global health
damage = randDmg()
if "Armour" in inventory:
damage = damage/2
else:
damage = damage
health-=damage
return health
print("Your new health is" + str(dmgCheck()))
print("Your new health is" + str(dmgCheck()))
That last bit could also be simplified by using pythons' string formating syntax:
print("Your new health is %s" % dmgCheck())
To do something similar using a Python Class you could use:
import random
class Game(object):
def __init__(self, inventory, health):
self.inventory = inventory
self.health = health
def randDmg(self):
dealtDamage = random.randint(1,10)
print("You have taken "+str(dealtDamage)+" damage.")
return dealtDamage
def dmgCheck(self):
damage = self.randDmg()
if "Armour" in self.inventory:
damage = damage/2
else:
damage = damage
self.health -= damage
return self.health
def play(self):
result = self.dmgCheck()
print("Your new health is %s" % result)
game = Game(["Armour","Sword","Healing Potion"], 100)
game.play()
game.play()

Resources