CMPE 150

Introduction to Computing

Fall 2021

Created by Gökçe Uludoğan

### Outline * How functions work * How to define your function * How to pass arguments to function * How to return data from function
### Functions * In math: `z = f(x, y)` * In programming: a block of code that perfoms a specific task * Python functions * Built-in * E.g. `print()`, `input()` * User defined
### Built-in functions * Defined somewhere * To use them, all you need to know is the interface of that function. * What **arguments** (if any) it takes * What **values** (if any) it returns
### Importance of Functions * Abstraction * You don't need to worry about how it works * Reusability * You can use a function over and over again * Modularity * Allows to break down complex processes into smaller steps
### Function Definition and Call ```python def <function_name>([<parameters>]): <statement(s)> <function_name>([<arguments>]) ``` | Component | Meaning | | ----------------- | ------------------------------------------------------------ | | `def` | The keyword for defining a function | | `<function_name>` | A valid function name | | `<parameters>` | An optional, comma-separated list of parameters | | `<statement(s)>` | A block of valid statements |

Code

def f():
    s = '-- Inside f()'
    print(s)

print('Before calling f()')
f()
print('After calling f()')

Code

def f():
    s = '-- Inside f()'
    print(s)

print('Before calling f()')
f()
print('After calling f()')

Output

Before calling f()
-- Inside f()
After calling f()

Code

def f():
    s = '-- Inside f()'
    print(s)

print('Before calling f()')
f()
print('After calling f()')

Output

Before calling f()
-- Inside f()
After calling f()

Flow

### Parameters & Arguments ```python def f(qty, item, price): print(qty, item, 'cost', price) f(6, 'apples', 8.75) ``` #### Output ``` 6 apples cost 8.75 ```
### Parameters & Arguments ```python def f(qty, item, price): print(qty, item, 'cost', price) f(6, 'apples', 8.75) ``` | Parameter | | Argument | | --------- | ---- | --------- | | `qty` | ← | `6` | | `item` | ← | `apples` | | `price` | ← | `8.75` |
### Parameters & Arguments ```python def f(qty, item, price): print(qty, item, 'cost', price) ``` The order matters: ```python f('apples', 8.75, 6) ``` ``` apples 8.75 cost 6 ```
### Parameters & Arguments * The number of arguments & parameters must be the same: * Too few arguments ```python f(6, 'apples') ``` ``` Traceback (most recent call last): File "", line 1, in f(6, 'apples') TypeError: f() missing 1 required positional argument: 'price' ```
### Parameters & Arguments * The number of arguments & parameters must be the same: * Too many arguments ```python f(6, 'apples', 8.75, 'oranges') ``` ``` Traceback (most recent call last): File "", line 1, in f(6, 'apples', 8.75, 'oranges') TypeError: f() takes 3 positional arguments but 4 were given ```
### Parameters & Arguments ```python def update_value(x): x = 100 a = 10 update_value(a) print(a) ```
### Parameters & Arguments ```python def update_value(x): x = 100 a = 10 update_value(a) print(a) ``` #### Output ``` 10 ```

Execution

### Return Statement * To pass data back to the caller * Update value: ```python def update_value(x): x = 100 return x a = 10 a = update_value(a) print(a) ```

Execution

### Names (Identifiers) * Names are given to objects (integers, strings, floats etc.) * When we do a variable assignment: ```python a = 2 ``` * **2** is an integer object stored in memory, and **a** is the name we associate it with
### Namespaces * A collection of names * Like a dictionary: * Keys = object names * Values = objects
### Types of Namespaces 1. Built-In 2. Global 3. Local
### 1. The Built-In Namespace * Contains the names of all of Python’s built-in objects * Available at all times when Python is running * Object types: int, float, bool, str, * Built-in functions: print(), input(), help(), len(), zip(), max()
### 2. The Global Namespace * Any names defined in the main program * Created when main program body starts, * Remains until the program terminates
### 3. The Local Namespace * A new namespace is created whenever a function executes * Local to the function * Remains until the function terminates

Code

def f():
    print('Start f()')
    print('End f()')
    
f()
print("Main program continues")
                 

Code

def f():
  print('Start f()')
  print('End f()')
  
f()
print("Main program continues")
               

Output

Start f()
End f()
Main program continues

Code

def f():
  print('Start f()')
  print('End f()')
  
f()
print("Main program continues")
               
  • The namespace created for the main program is the global namespace.

  • When the main program calls f(), Python creates a new namespace for f().

  • The namespace created for f() is the local namespace.

Variable Scope

If your code refers to the name x, Python searches for x in the following namespaces in the order shown:

  1. Local
  2. Global
  3. Built-in

Search using the LGB rule

Code

def f():     
  print(x)
  
x = 'global'
f()
               

Code

def f():     
  print(x)
  
x = 'global'
f()
               

Output

global

Code

def f():     
  print(x)
  
x = 'global'
f()
               

Output

global
  • x is defined in only one location.

  • It’s outside f(), so it's in the global scope

Code

def f():
  x = 'local'     
  print(x)
		       
x = 'global'       
f()
               

Code

def f():
  x = 'local'     
  print(x)
		       
x = 'global'       
f()
               

Output

local

Code

def f():
  x = 'local'     
  print(x)
		       
x = 'global'       
f()
               

Output

local
  • Line 1 defines x in the global scope.

  • Line 4 defines x again in the local scope.

  • According to the LGB rule, the interpreter finds the value from the local space before looking in the global space.

Code

def f():
  x = 'local'
  print(x)

x = 'global'
f()
print(x)
               

Code

def f():
  x = 'local'
  print(x)

x = 'global'
f()
print(x)
               

Output

local
global

Code

def f():
  x = 'local'
  print(x)

x = 'global'
f()
print(x)
               

Output

local
global
  • Line 1: x in the global scope. Line 4: x in the local scope.

  • When f() is called, the local namespace of f() is active, therefore x = "local".

  • After f() terminates, the local namespace of f() terminates too. Therefore, back in the main program, x = "global".

Execution

Code

def f():
  print(x)

f()
               

Code

def f():
  print(x)

f()
               

Output

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "<stdin>", line 2, in f
  print(x)
NameError: name 'x' is not defined

Code

def f():
  print(x)

f()
               

Output

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "<stdin>", line 2, in f
  print(x)
NameError: name 'x' is not defined
  • x isn't defined at all.

  • The print() statement generates a NameError exception.

References

  1. https://pythontutor.com/
  2. https://realpython.com/defining-your-own-python-function/