Hi I just finished a VERY Basic airline reservation system. Wanted some feedback please let me know what you all think, if I am obfuscating information or passing parameters where I shouldn't or if things don't make sense
Airline Class: handles booking and refunds
Passenger: Has a seat assignment, and a balance to pay for ticket
Seat:
Firstclass and Coach
Plane:
a dictionary object holding seats and passengers get passed as values to those seats
here is my code:
class Airline:
def __init__(self, name=None):
self._name = name
self._booked = []
def get_name(self):
return self._name
def set_name(self, name):
self._name = name
def book(self, passenger, plane, cls=None):
while cls not in ['first class', 'coach']:
cls = input("Please pick a seat: First class or Coach ").lower()
if cls not in ['first class', 'coach']:
print("Please select either from 'first class' or 'coach'")
pass
if cls == 'first class':
first_class = ([(number, seat) for number, seat in enumerate(plane.capacity)][0:10])
choice = None
while choice not in range(10):
try:
choice = int(input(f"Please select a number between 0 and 9 for your seats: "))
except ValueError:
print("Please select a valid number between 0 and 9")
if choice in self._booked:
print(f"That seat is taken please choose another seat\n"
f"These seats are booked: {self._booked}")
choice = None
for seat in first_class:
if seat[0] == choice:
plane.capacity[seat[1]] = passenger
passenger._balance = passenger._balance - seat[1].price
self._booked.append(seat[0])
passenger._assignment = seat[1].tier + f" seat {seat[0]}"
else:
coach = ([(number, seat) for number, seat in enumerate(plane.capacity)][10:50])
choice = None
while choice not in range(10, 50):
try:
choice = int(input(f"Please select a number between 10 and 50 for your seats: "))
except ValueError:
print("Please select a valid number between 10 and 50")
if choice in self._booked:
print(f"That seat is taken please choose another seat\n"
f"These seats are booked: {self._booked}")
choice = None
for seat in coach:
if seat[0] == choice:
plane.capacity[seat[1]] = passenger
passenger._balance = passenger._balance - seat[1].price
self._booked.append(seat[0])
passenger._assignment = seat[1].tier + f" seat {seat[0]}"
def refund(self, passenger, plane):
for i, (seat, person) in enumerate(plane.capacity.items()):
if person == passenger:
plane.capacity[seat] = None
passenger._balance = passenger._balance + seat.price
passenger._assignment = None
self._booked.remove(i)
class Passenger:
def __init__(self, balance=1000, assignment=None):
self._balance = balance
self._assignment = assignment
def get_balance(self):
return self._balance
def get_assignment(self):
return self._assignment
class Seat:
def __init__(self):
pass
class FirstClass(Seat):
def __init__(self):
super().__init__()
self.tier = 'First Class'
self.price = 500
class Coach(Seat):
def __init__(self):
super().__init__()
self.tier = 'Coach'
self.price = 100
class Plane:
def __init__(self):
self.capacity = {}
temp_capacity = [] # Create a temporary list to append seats into ( this will be the seats in the airplane)
for i in range(10): # first 10 seats are first class
temp_capacity.append(FirstClass())
for i in range(10, 50): # last 40 seats are coach class
temp_capacity.append(Coach())
for seat in temp_capacity:
self.capacity[seat] = None # Each seat has no value(person) assigned
def view_plane(self):
for i, k in self.capacity.items():
print(f"{i} : {k}")
def get_available_seats(self):
count = 0
for value in self.capacity.values():
if value is None:
count += 1
return count
Running this below: (Will output how I envisioned the plane to be built and how seats are assigned to passengers, etc.)
plane = Plane()
p = Passenger()
p2 = Passenger()
p3 = Passenger()
airline = Airline()
plane.view_plane()
airline.book(p, plane)
airline.book(p2, plane)
print(airline._booked)
print(f"passenger 1 balance: {p.get_balance()}\n"
f"passenger 1 assignment: {p.get_assignment()}\n"
f"passenger 2 balance: {p2.get_balance()}\n"
f"passenger 2 assignment: {p2.get_assignment()}\n"
f"Number of seats available: {plane.get_available_seats()}\n"
f"Number of seats booked: {len(airline._booked)}")
plane.view_plane()
airline.book(p3, plane)
plane.view_plane()
print("--------------")
print(airline._booked)
print(f"passenger 1 balance: {p.get_balance()}\n"
f"passenger 1 assignment: {p.get_assignment()}\n"
f"passenger 2 balance: {p2.get_balance()}\n"
f"passenger 2 assignment: {p2.get_assignment()}\n"
f"passenger 3 balance: {p3.get_balance()}\n"
f"passenger 3 assignment: {p3.get_assignment()}\n"
f"Number of seats available: {plane.get_available_seats()}\n"
f"Number of seats booked: {len(airline._booked)}")
print("----------------")
airline.refund(p2, plane)
print(airline._booked)
print(f"passenger 1 balance: {p.get_balance()}\n"
f"passenger 1 assignment: {p.get_assignment()}\n"
f"passenger 2 balance: {p2.get_balance()}\n"
f"passenger 2 assignment: {p2.get_assignment()}\n"
f"passenger 3 balance: {p3.get_balance()}\n"
f"passenger 3 assignment: {p3.get_assignment()}\n"
f"Number of seats available: {plane.get_available_seats()}\n"
f"Number of seats booked: {len(airline._booked)}")
Please let me know better ways to do this or better interfaces etc. I will be slowly adding more complexity but my main goal was having the airline be able to book and place passengers in the plane and refund them from their seat while updating the planes capacity during these changes.
Will be adding multiple planes per airline which will undoubtedly change the structure of some of the classes but for right now let me know if what I have allows for the basic booking and refunding operations to work efficiently and if the classes are setup properly or what improvements can be made.
-
1\$\begingroup\$ Nicely written code, very easy to follow. Good job \$\endgroup\$user228914– user2289142020年10月08日 12:33:59 +00:00Commented Oct 8, 2020 at 12:33
2 Answers 2
Nice implementation, it's easy to understand and well structured. Few suggestions:
Seat class
class Seat:
def __init__(self):
pass
class FirstClass(Seat):
def __init__(self):
super().__init__()
self.tier = 'First Class'
self.price = 500
class Coach(Seat):
def __init__(self):
super().__init__()
self.tier = 'Coach'
self.price = 100
A Seat
is supposed to have a tier and a price, but this information is not in the main class, only in the subclasses.
Consider to add tier
and price
in the Seat
constructor. I also suggest to add a number for the Seat
class.
Typically, the price of the seat is not bound to a tier forever. The price of a seat depends on the flight. For example, the same seat can have two different prices for two flights on the same day. Consider this when you will expand the design.
Passenger class
class Passenger:
def __init__(self, balance=1000, assignment=None):
self._balance = balance
self._assignment = assignment
- A passenger should have at least a name, but most importantly an
id
. - I am not sure why you use underscore variables here. Is because they are for internal use? But the class
Airline
uses them in thebook
method likepassenger._balance = ..
. Also the classSeat
does not use underscore variables so I am a bit confused. Consider to use them consistently.
Book method
if choice in self._booked
: here_booked
is a list that contains all the reserved seats for all the planes. What happens if there is a reservation for the same seat number of two different planes? Consider to associate the reservations to a plane or better to a flight.- Performance: at every reservation, a new
first_class
is created:
This is an expensive operation that can be avoided. Consider to create the first class in the plane and then request the result with a method.if cls == 'first class': first_class = ([(number, seat) for number, seat in enumerate(plane.capacity)][0:10])
- Magic numbers and duplication:
The code to ask the user about tier and seat number is duplicated and there are some "magic numbers" likeif cls == 'first class': first_class = ([(number, seat) for number, seat in enumerate(plane.capacity)][0:10]) choice = None while choice not in range(10): try: choice = int(input(f"Please select a number between 0 and 9 for your seats: ")) #... else: coach = ([(number, seat) for number, seat in enumerate(plane.capacity)][10:50]) choice = None while choice not in range(10, 50): try: choice = int(input(f"Please select a number between 10 and 50 for your seats: ")) #...
while choice not in range(10)
. In this case 10 is the number of seats in the first class of the given plane. I think it should be a property of theplane
that has a first class with a certain number of seats. You can consider something like this:tier = plane.get_tier(cls) # tier is first class or coach choice = None while choice not in tier.get_seats_range(): try: choice = int(input(f"Please select a number between {tier.get_seats_range()[0]} and {tier.get_seats_range()[1]} for your seats: "))
Here is some minor things on the class Airline
class Airline:
def __init__(self, name=None):
self._name = name
self._booked = []
def get_name(self):
return self._name
def set_name(self, name):
self._name = name
Is strange to me that you can have an airline that have no name, so I would recommend to make the argument name mandatory. Conceptually is more correct from my point of view.
The other thing is that in python there is no concept of getters and setters, instead of that there is properties.
class Airline:
def __init__(self, name):
self._name = name
self._booked = []
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
Explore related questions
See similar questions with these tags.