Validation and invariants

It's good practice for the initializer of an object to establish so-called class invariants. The invariants are truths about objects of that class that should endure for the lifetime of the object. One such invariant for flights is that the flight number always begins with an upper case two-letter airline code followed by a three or four digit route number.

In Python, we establish class invariants in the __init__() method and raise exceptions if they can't be attained:

class Flight:

def __init__(self, number):
if not number[:2].isalpha():
raise ValueError("No airline code in '{}'".format(number))

if not number[:2].isupper():
raise ValueError("Invalid airline
code'{}'".format(number))


if not (number[2:].isdigit() and int(number[2:]) <= 9999):
raise ValueError("Invalid route
number'{}'".format(number))


self._number = number

def number(self):
return self._number

We use string slicing and various methods of the string class to perform validation. For the first time in this book we also see the logical negation operator not.

Ad hoc testing in the REPL is a very effective technique during development:

>>> from airtravel import Flight
>>> f = Flight("SN060")
>>> f = Flight("060")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 8, in __init__
raise ValueError("No airline code in '{};".format(number))
ValueError: No airline code in '060'
>>> f = Flight("sn060")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 11, in __init__
raise ValueError("Invalid airline code '{}'".format(number))
ValueError: Invalid airline code 'sn060'
>>> f = Flight("snabcd")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 11, in __init__
raise ValueError("Invalid airline code '{}'".format(number))
ValueError: Invalid airline code 'snabcd'
>>> f = Flight("SN12345")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./airtravel.py", line 11, in __init__
raise ValueError("Invalid airline code '{}'".format(number))
ValueError: Invalid airline code 'sn12345'

Now that we're sure of having a valid flight number, we'll add a second method to return just the airline code. Once the class invariants have been established, most query methods can be very simple:

def airline(self):
return self._number[:2]
..................Content has been hidden....................

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