Programming in Python

Functions

Gerald Senarclens de Grancy

Terminology

Code Reuse

  • A single copy of code can be used elsewhere
  • Basis of any library
  • Important for maintenance

Case Sensitivity

  • Uppercase and lowercase letters are treated as distinct
  • Python, Bash and Linux are case sensitive

Scope

  • Region of code in which a name is known (or visible) and accessible
  • In scope/ out of scope
  • Python blocks do not create a new scope
  • Modules, classes, and functions do
  • Don't use global variables
  • Global constants (all caps) are ok

DRY - Don't Repeat Yourself

Formulated by Andy Hunt and Dave Thomas in "The Pragmatic Programmer"

  • Fundamental programming principle
  • Every piece of knowledge [...] should have a single representation
  • Duplication is waste (=> maintenance!!)
  • There should be only one obvious [...] way to accomplish a task

Steve Smith in [Henney (2010), p. 60f]

Functions

A function gives a name to a block of code

The named block of code can be executed by "calling" the function name

Function names should state what the function does or what it returns

  • Snippets of code usable from the rest of the program
  • Separate out common actions
  • Package up and parameterize functionality
  • Avoid code duplication and allow reusing code
  • Maintenance becomes easier
  • kloc/ sloc is a dangerous metric

When using appropriate function names, code becomes easier to read

# ...delta_x, delta_y are defined, `sqrt` is available
delta_x2 = delta_x * delta_x
delta_y2 = delta_y * delta_y
distance = sqrt(delta_x2 + delta_y2)
# vs. (requires `hypot` function to be available)
distance = hypot(delta_x, delta_y)

Arguments and Parameters

  • Functions can be parameterized to make them more generic
  • Parameters are available to functions as variables
  • Arguments are values passed to a function
  • Argument values are accessed through parameters

Return Statement

  • Causes execution to leave the current function
  • Execution is resumed where the function was called
  • Return statements allow a function to specify a return value
  • A return value is passed back to the code that called the function

Python Functions

() after a function name calls (executes) that function

(.) indicates that a function expects one or more arguments

  • Built in functions (BIFs) / methods we already know
    • print(.), open(.), min(.), ...
    • string.upper(), string.split(.), ...
  • Standard library functions we already know
    • math.sqrt(.), math.hypot(.), ...
    • random.randint(.)

Docstrings

"""..."""

  • String literal appearing as the first expression in a function
  • Ignored when the function is executed
  • Put into the function's __doc__ attribute
  • Available via introspection
  • Canonical place for documentation of the function

Syntax

def <funcname>(parameter1, parameter2, ..., parameterN) [-> annotation]:
    """
    Textual explanation of what the function is supposed to do.
    """
    <suite>

Example

#!/usr/bin/env python3

def interest(capital, rate, years=1):
    """
    Return the total interest of investing `capital` at `rate`.
    """
    value = capital * (1 + rate) ** years
    return value - capital

print(interest(100, 0.03))
result = interest(100, 0.03, 3)
profit = interest(1300, 0.025, 5)

Visualize execution

Python 3 Video Tutorial - Functions

Function Parameters

Python passes references to objects

No need to worry when passing immutable objects

Example - Pass by Reference

#!/usr/bin/env python3

def print_uppercase(text):
    """
    Print the passed text as upper case.
    """
    print(text.upper())
a_text = "Programming is fun!"
result = print_uppercase(a_text)

def print_sorted_list(l):
    l.sort()
    print(l)
a_list = [5, 3, 7, 1, 4]
another_result = print_sorted_list(a_list)

Visualize execution

It is possible to define default values for parameters

Default parameters can be omitted when passing arguments to a function

Example - Default Parameters

#!/usr/bin/env python

def power(base, exp=2):
    return base ** exp

power(3, 3)  # -> 27
power(5)  # -> 25

Visualize execution

Arguments may be passed matching the parameters' position or name

Example - Positional and Keyword Arguments

#!/usr/bin/env python3

def interest(capital=1000, rate=0.04, years=1):
    """
    Return the total interest of investing `capital` at `rate`.
    """
    value = capital * (1 + rate) ** years
    return value - capital

print(interest(100, 0.03))
profit = interest(capital=1300, rate=0.025, years=5)
profit = interest(rate=0.03, years=3, capital=1200)
profit = interest(years=5)
profit = interest(1300, years=5)
result = interest(1000 + interest(rate=0.06), 0.03, 3)

Visualize execution

ifmain Pattern

Define functions before using them

  • Best practice is to avoid regular code in the global scope
  • Instead, define a main(.) function
  • Use ifmain pattern at the end of the file to call the main function
  • Allows re-use of file as Python module
if __name__ == "__main__":
    sys.exit(main())

sys.exit(main()) passes main's return value to the shell

0 means success, everything else means failure

Method

Function associated with an object's data

  • Method:
  • a_string = 'Python'
    a_string.upper()
  • Function:
  • min(3, 4, 2)
  • Function or Method?
  • text = 'a,b,c'
    text.split(',')

Wikipedia - Method

Function Composition vs. Method Chaining

Common syntax for invoking multiple function respectively method calls

Function composition
The result of one function is argument of another function
Function composition is done "inside out", for example
sin(sqrt(12))
Method chaining
Methods returning an object are chained together in a single statement
Method chaining is performed from left to right, for example
text.upper().split()

Lambda Functions

Python supports lambda (anonymous or unnamed) functions

lambda [parameter_list]: expression

They behave like a function object defined with:

def <lambda>(parameters):
    return expression

Lambda functions are expressions that can be created at their point of use

They are limited in comparison to regular functions (only a single expression)

Example

Lambda functions are useful as arguments, e.g. for sorting.

#!/usr/bin/env python3

a_list = [3, 4, 19, 11, 1, 4, 6, 8, 5, 2, 0, 12, 13, 3]
a_list.sort(key=lambda x: x % 3)  # sort by remainder of division by 3
print(a_list)

Visualize execution

Pair Programming

Definition

  • Agile software development technique
  • Two programmers work together at one workstation
  • The driver writes code; the navigator reviews each line as it is typed
  • The two programmers switch roles frequently

Wikipedia - Pair programming

Motivations

  • Skills and knowledge are distributed
  • Increases the bus factor (also in the interest of the employee)
  • Gives partners to discuss problems
  • Code quality is improved
    Having enough eyes, all bugs seem shallow. - Linus Torvalds
  • Mitigates interruptions (keeps the flow)
  • New team members get to know other team members

Gudny Hauknes et. al. in [Henney (2010), pg 128f]

Rules for Pair Programming

  • Be patient with developers less experienced than you
    (explaining improves your own understanding!)
  • Frequent rotation of pairs is crucial (use agreed rule of rotation)
  • Adjust the rotation rule when necessary
  • A task doesn't need to be completed before rotating teams

Gudny Hauknes et. al. in [Henney (2010), pg 128f]

Questions
and feedback...

Literature

Andrew Hunt and David Thomas The Pragmatic Programmer, 20th Anniversary Edition Addison Wesley (2019) buy on Amazon
Kevlin Henney 97 Things Every Programmer Should Know O'Reilly and Associates (March 18, 2010) buy on Amazon