Python 3home |
Introduction to Python
davidbpython.com
Variable names initialized inside a function are local to the function.
def myfunc():
tee = 10
return tee
var = myfunc()
print(var) # 10
print(tee) # NameError ('tee' does not exist here)
Ex. 12.9
Any variable defined in our code outside a function is global.
var = 'hello global' # global variable
def myfunc():
print(var) # this global is available here
myfunc() # hello global
Ex. 12.10 - 12.11
Functions that do not touch outside variables, and do not create "side effects" (for example, calling exit(), print() or input()), are considered "pure" -- and are preferred.
"Pure" functions have the following characteristics:
"Outside" (Global) variables are ones defined outside the function -- they should be avoided.
wrong way: referring to an outside variable inside a function
val = '5' # defined outside any function
def doubleit():
dval = int(val) * 2 # BAD: function refers to "global" variable 'val'
return dval
new_val = doubleit()
right way: passing outside variables as arguments
val = '5' # defined outside any function
def doubleit(arg):
dval = int(arg) * 2 # GOOD: refers to the same value '5',
return dval # but accessed through local
# argument 'arg'
new_val = doubleit(val) # passing variable to function -
# correct way to get a value into the function
print(), input(), exit() all "touch" the outside world and in many cases should be avoided inside functions.
Although it is of course possible (and sometimes practical) to use these built-in functions inside our function, we should avoid them if we are interested in making a function "pure". It should also be noted that it's fine to use any of these in a function during development - they are all useful development tools.
exit() should not be called inside a function.
def doubleit(arg):
if not arg.isdigit():
raise ValueError('arg must be all digits') # GOOD: error signaled with raise
dval = int(arg) * 2
return dval
val = input('what is your value? ')
new_val = doubleit(val)
raise creates an error condition (exception) that usually terminates program execution.
To raise an exception, we simply follow raise with the type of error we would like to raise, and an optional message:
raise ValueError('please use a correct value')
You may raise any existing exception (you may even define your own). Here is a list of common exceptions:
| Exception Type | Reason |
|---|---|
| TypeError | the wrong type used in an expression |
| ValueError | the wrong value used in an expression |
| FileNotFoundError | a file or directory is requested that doesn't exist |
| IndexError | use of an index for a nonexistent list/tuple item |
| KeyError | a requested key does not exist in the dictionary |
Globals should be used inside functions only in select circumstances.
STATE_TAX = .05 # ALL CAPS designates a "constant"
def calculate_bill(bill_amount, tip_pct):
tax = bill_amount * STATE_TAX # int, 5
tip = bill_amount * tip_pct # float, 20.0
total_amount = bill_amount + tax + tip # float, 125.0
return total_amount
total = calculate_bill(100, .20) # float, 125.0
Here are some positive reasons to strive for purity.
You may have noticed that these "impure" practices do not cause Python errors. So why should we avoid them?
The above perspective will become clearer as you write longer programs. As your programs become more complex, you will be confronted with more complex errors that are sometimes difficult to trace. Over time you'll realize that the best practice of using pure functions enhances the "quality" of your code -- making it easier to write, maintain, extend and understand the programs you create.
Again, please note that during development it is perfectly allowable to call print(), exit() or input() from inside a function. We may also decide on our own that this is all right in shorter programs, or ones that we working on in isolation. It is with longer programs and collaborative projects where purity becomes more important.
Let's discuss some essential elements of a program.
Here are the main components of a properly formatted program. Please Sse the tip_calculator.py file in your files directory for an example:
review of tip_calculator.py
Four kinds of variables: (L)ocal, (E)nclosing, (G)lobal and (B)uiltin.
filename = 'pyku.txt' # 'filename': global
# 'get_text': global (function name is a
# variable as well)
def get_text(fname): # 'fname': local
fh = open(fname) # 'fh': local; 'open': builtin
text = fh.read() # 'text': local
return text
txt = get_text(filename) # 'txt': global
print(txt) # 'print': builtin