Organizing our software
Python gives us a number of ways to organize software into conceptual units. Long, sprawling scripts are hard to read, repair, or extend. Python offers us packages, modules, classes, and functions. We'll see different organizing techniques throughout our agent training. We'll start with function definition.
We've used a number of Python's built-in functions in the previous sections. Defining our own function is something we do with the def
statement. A function definition allows us to summarize (and in some cases generalize) some processing. Here's a simple function we can use to get a decimal value from a user:
def get_decimal(prompt): value= None while value is None: entry= input(prompt) try: value= Decimal(entry) except decimal.InvalidOperation: print("Invalid: ", entry) return value
This follows the design we showed previously, packaged as a separate function. This function will return a proper Decimal
object: the value of the value
variable. We can use our get_decimal()
function like this:
grd_usd= get_decimal("GRD conversion: ")
Python allows a great deal of variability in how argument values are supplied to functions. One common technique is to have an optional parameter, which can be provided using a keyword argument. The print()
function has this feature, we can name a file by providing a keyword argument value.
import sys print("Error", file=sys.stderr)
If we don't provide the file
parameter, the sys.stdout
file is used by default.
We can do this in our own functions with the following syntax:
def report( grd_usd, target=sys.stdout ): lunch_grd= Decimal('12900') bribe_grd= 50000 cab_usd= Decimal('23.50') lunch_usd= (lunch_grd/grd_usd).quantize(PENNY) bribe_usd= (bribe_grd/grd_usd).quantize(PENNY) receipt_1 = "{0:12s} {1:6.2f} USD" receipt_2 = "{0:12s} {1:8.0f} GRD {2:6.2f} USD" print( receipt_2.format("Lunch", lunch_grd, lunch_usd), file=target ) print( receipt_2.format("Bribe", bribe_grd, bribe_usd), file=target ) print( receipt_1.format("Cab", cab_usd), file=target ) print( receipt_1.format("Total", lunch_usd+bribe_usd+cab_usd), file=target )
We defined our report
function to have two parameters. The grd_usd
parameter is required. The target
parameter has a default value, so it's optional.
We're also using a global variable, PENNY
. This was something we set outside the function. The value is usable inside the function.
The four print()
functions provide the file parameter using the keyword syntax: file=target
. If we provided a value for the target
parameter, that will be used; if we did not provide a value for target
, the default value of the sys.stdout
file will be used. We can use this function in several ways. Here's one version:
rate= get_decimal("GRD conversion: ") print(rate, "GRD = 1 USD") report(rate)
We provided the grd_usd
parameter value positionally: it's first. We didn't provide a value for the target
parameter; the default value will be used.
Here's another version:
rate= get_decimal("GRD conversion: ") print(rate, "GRD = 1 USD", file=sys.stdout) report(grd_usd=rate, target=sys.stdout)
In this example, we used the keyword parameter syntax for both the grd_usd
and target
parameters. Yes, the target
parameter value recapitulated the default value. We'll look at how to create our own files in the next section.