Allocating seats to passengers

Now we'll add behavior to Flight to allocate seats to passengers. To keep this simple, a passenger will simply be a string name:

class Flight:

# ...

def allocate_seat(seat, passenger):
"""Allocate a seat to a passenger.

Args:
seat: A seat designator such as '12C' or '21F'.
passenger: The passenger name.

Raises:
ValueError: If the seat is unavailable.
"""
rows, seat_letters = self._aircraft.seating_plan()

letter = seat[-1]
if letter not in seat_letters:
raise ValueError("Invalid seat letter {}".format(letter))

row_text = seat[:-1]
try:
row = int(row_text)
except ValueError:
raise ValueError("Invalid seat row {}".format(row_text))

if row not in rows:
raise ValueError("Invalid row number {}".format(row))

if self._seating[row][letter] is not None:
raise ValueError("Seat {} already occupied".format(seat))

self._seating[row][letter] = passenger

Most of this code is validation of the seat designator and it contains some interesting snippets:

  • Line 6: Methods are functions, so deserve docstrings too.

  • Line 17: We get the seat letter by using negative indexing into the seat string.

  • Line 18: We test that the seat letter is valid by checking for membership of seat_letters using the in membership testing operator.

  • Line 21: We extract the row number using string slicing to take all but the last character.

  • Line 23: We try to convert the row number substring to an integer using the int() constructor. If this fails, we catch the ValueError and in the handler raise a new ValueError with a more appropriate message payload.

  • Line 27: We conveniently validate the row number by using the in operator against the rows object which is a range. We can do this because range() objects support the container protocol.

  • Line 30: We check that the requested seat is unoccupied using an identity test with None. If it's occupied we raise a ValueError.

  • Line 33: If we get this far, everything is is good shape, and we can assign the seat.

This code also contains a bug, which we'll discover soon enough!

Trying our seat allocator at the REPL:

>>> from airtravel import *
>>> f = Flight("BA758", Aircraft("G-EUPT", "Airbus A319",
... num_rows=22, num_seats_per_row=6))
>>> f.allocate_seat('12A', 'Guido van Rossum')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: allocate_seat() takes 2 positional arguments but 3 were
given

Oh dear! Early on in your object-oriented Python career you're likely to see TypeError messages like this quite often. The problem has occurred because we forgot to include the self argument in the definition of the allocate_seat() method:

def allocate_seat(self, seat, passenger):
# ...

Once we fix that, we can try again:

>>> from airtravel import *
>>> from pprint import pprint as pp
>>> f = Flight("BA758", Aircraft("G-EUPT", "Airbus A319",
... num_rows=22, num_seats_per_row=6))
>>> f.allocate_seat('12A', 'Guido van Rossum')
>>> f.allocate_seat('12A', 'Rasmus Lerdorf')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 57, in allocate_seat
raise ValueError("Seat {} already occupied".format(seat))
ValueError: Seat 12A already occupied
>>> f.allocate_seat('15F', 'Bjarne Stroustrup')
>>> f.allocate_seat('15E', 'Anders Hejlsberg')
>>> f.allocate_seat('E27', 'Yukihiro Matsumoto')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 45, in allocate_seat
raise ValueError("Invalid seat letter {}".format(letter))
ValueError: Invalid seat letter 7
>>> f.allocate_seat('1C', 'John McCarthy')
>>> f.allocate_seat('1D', 'Richard Hickey')
>>> f.allocate_seat('DD', 'Larry Wall')
Traceback (most recent call last):
File "./airtravel.py", line 49, in allocate_seat
row = int(row_text)
ValueError: invalid literal for int() with base 10: 'D'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 51, in allocate_seat
raise ValueError("Invalid seat row {}".format(row_text))
ValueError: Invalid seat row D

>>> pp(f._seating)
[None,
{'A': None,
'B': None,
'C': 'John McCarthy',
'D': 'Richard Hickey',
'E': None,
'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': 'Guido van Rossum','B': None,'C': None,'D': None,'E': None,
'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None,'B': None,'C': None,'D': None,'E': 'Anders Hejlsberg',
'F': 'Bjarne Stroustrup'},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None},
{'A': None, 'B': None, 'C': None, 'D': None, 'E': None, 'F': None}]

The Dutchman is quite lonely there in row 12, so we'd like to move him back to row 15 with the Danes. To do so, we'll need a relocate_passenger() method.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset