Don't Repeat Yourself. In programming, if you use the same block of code multiple times, it belongs in a function.
A Function is a reusable block of code that performs a specific task. In AI, we use functions for everything from calculating accuracy to processing images.
You create a function using the def keyword, followed by the function name and parentheses. Inside the parentheses, you define parameters (inputs). The return statement sends a result back.
Imagine calculating the average error for multiple different models. Instead of writing the math every time, we write an error() function once.
The names in the def line are parameters; the values you pass when calling are arguments. Arguments can be matched by position or by name, and parameters can have default values that are used when the caller omits them. Parameters with defaults must come after those without.
def accuracy(predictions, actuals, as_percent=False):
correct = 0
for p, a in zip(predictions, actuals):
if p == a:
correct += 1
value = correct / len(actuals)
return value * 100 if as_percent else value
print(accuracy([1, 0, 1, 1], [1, 0, 0, 1])) # 0.75
print(accuracy([1, 0, 1, 1], [1, 0, 0, 1], as_percent=True)) # 75.0Here zip() walks two lists in step, which is cleaner than indexing with range(len(...)). Calling with as_percent=True by name makes the call self-documenting.
print() shows something to a human; return hands a value back to the code that called the function so it can be stored or used in further calculations. A function without a return statement returns None. Beginners often write a function that prints its answer, then discover they cannot use the result in an expression. As a rule, make functions return values and let the calling code decide whether to print.
A function can return several values at once; Python packs them into a tuple which you can unpack on the left:
def min_max(values):
return min(values), max(values)
low, high = min_max([3, 9, 4, 1])
print(low, high) # 1 9Variables created inside a function are local: they exist only while the function runs and are invisible outside. This is a feature, not a limitation, because it means two functions can both use a variable called total without interfering. A function can read a global variable, but assigning to a name inside a function creates a new local variable instead of changing the global one.
threshold = 0.5
def classify(p):
label = "pos" if p >= threshold else "neg" # reads the global
return label
print(classify(0.7)) # pos
print(label) # NameError: label exists only inside classifySuppose you compare three models. Without a function you would copy the counting loop three times, and a bug fix would need three edits. With a function, the logic lives in one place. Functions can also call each other, which is how larger programs are assembled from small, testable pieces:
def normalize(value, min_val, max_val):
return (value - min_val) / (max_val - min_val)
def normalize_all(values):
lo, hi = min(values), max(values)
return [normalize(v, lo, hi) for v in values]
print(normalize_all([10, 20, 40])) # [0.0, 0.3333333333333333, 1.0]Note the edge case: if every value is equal, hi - lo is zero and the division fails. Thinking about such inputs before they happen is a habit that separates reliable code from fragile code.
A string placed on the first line inside a function is its docstring. Tools and the built-in help(accuracy) display it. Choose verbs for function names (calculate_accuracy, normalize) and keep each function focused on one job.
accuracy without parentheses is the function object, not its result.def add(x, items=[]) reuses the same list across calls. Use items=None and create the list inside.return in the first iteration ends the function immediately.TypeError that names the function and what was expected.def defines a function; parameters receive arguments; defaults make parameters optional.return sends a value back; without it a function returns None.Let's write a reusable utility function to calculate classification accuracy.
calculate_accuracy that takes two lists as parameters: predictions and actuals.range(len(predictions)) in a loop).return the calculated accuracy.preds = [1,0,1,1] and acts = [1,0,0,1] and print the result.