0% found this document useful (0 votes)
3 views46 pages

Chapter 3

The document discusses the concept of functions as first-class objects in Python, detailing how they can be assigned to variables, stored in lists or dictionaries, and passed as arguments. It also covers nested functions, closures, and the use of decorators to modify function behavior. Key concepts such as scope, the global and nonlocal keywords, and practical examples of function definitions and decorators are provided.

Uploaded by

Doménica Amores
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views46 pages

Chapter 3

The document discusses the concept of functions as first-class objects in Python, detailing how they can be assigned to variables, stored in lists or dictionaries, and passed as arguments. It also covers nested functions, closures, and the use of decorators to modify function behavior. Key concepts such as scope, the global and nonlocal keywords, and practical examples of function definitions and decorators are provided.

Uploaded by

Doménica Amores
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Functions as objects

WRITING FUNCTIONS IN PYTHON

Shayne Miel
Software Architect @ Duo Security
Functions are just another type of object
Python objects:

def x():
pass
x = [1, 2, 3]
x = {'foo': 42}
x = [Link]()
x = 'This is a sentence.'
x = 3
x = 71.2
import x

WRITING FUNCTIONS IN PYTHON


Functions as variables
def my_function():
print('Hello')
x = my_function
type(x)

<type 'function'>

x()

Hello

PrintyMcPrintface = print
PrintyMcPrintface('Python is awesome!')

Python is awesome!

WRITING FUNCTIONS IN PYTHON


Lists and dictionaries of functions
list_of_functions = [my_function, open, print]
list_of_functions[2]('I am printing with an element of a list!')

I am printing with an element of a list!

dict_of_functions = {
'func1': my_function,
'func2': open,
'func3': print
}
dict_of_functions['func3']('I am printing with a value of a dict!')

I am printing with a value of a dict!

WRITING FUNCTIONS IN PYTHON


Referencing a function
def my_function():
return 42

x = my_function
my_function()

42

my_function

<function my_function at 0x7f475332a730>

WRITING FUNCTIONS IN PYTHON


Functions as arguments
def has_docstring(func): def no():
"""Check to see if the function return 42
`func` has a docstring.
def yes():
Args: """Return the value 42
func (callable): A function. """
return 42
Returns:
bool
has_docstring(no)
"""
return func.__doc__ is not None
False

has_docstring(yes)

True

WRITING FUNCTIONS IN PYTHON


Defining a function inside another function
def foo():
x = [3, 6, 9]

def bar(y):
print(y)

for value in x:
bar(x)

WRITING FUNCTIONS IN PYTHON


Defining a function inside another function
def foo(x, y):
if x > 4 and x < 10 and y > 4 and y < 10:
print(x * y)

def foo(x, y):


def in_range(v):
return v > 4 and v < 10

if in_range(x) and in_range(y):


print(x * y)

WRITING FUNCTIONS IN PYTHON


Functions as return values
def get_function():
def print_me(s):
print(s)
# returns the function 'print_me'
return print_me

new_func = get_function()
new_func('This is a sentence.')

This is a sentence.

WRITING FUNCTIONS IN PYTHON


Let's practice!
WRITING FUNCTIONS IN PYTHON
Scope
WRITING FUNCTIONS IN PYTHON

Shayne Miel
Software Architect @ Duo Security
Names

WRITING FUNCTIONS IN PYTHON


Names

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


Scope
x = 7 foo()
y = 200
print(x)
42
200
7

print(x)
def foo():
x = 42
7
print(x)
print(y)

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


Scope

WRITING FUNCTIONS IN PYTHON


The global keyword
x = 7 x = 7

def foo(): def foo():


x = 42 global x
print(x) x = 42
print(x)
foo()
foo()

42
42

print(x)
print(x)

7
42

WRITING FUNCTIONS IN PYTHON


The nonlocal keyword
def foo(): def foo():
x = 10 x = 10

def bar(): def bar():


x = 200 nonlocal x
print(x) x = 200
print(x)
bar()
print(x) bar()
print(x)
foo()
foo()

200
10 200
200

WRITING FUNCTIONS IN PYTHON


Let's practice!
WRITING FUNCTIONS IN PYTHON
Closures
WRITING FUNCTIONS IN PYTHON

Shayne Miel
Software Architect @ Duo Security
Attaching nonlocal variables to nested functions
def foo(): Closures!
a = 5
def bar():
type(func.__closure__)
print(a)
return bar
<class 'tuple'>

func = foo()

len(func.__closure__)
func()

1
5

func.__closure__[0].cell_contents

WRITING FUNCTIONS IN PYTHON


Closures and deletion
x = 25 len(my_func.__closure__)

def foo(value):
1
def bar():
print(value)
return bar my_func.__closure__[0].cell_contents

my_func = foo(x)
my_func() 25

25

del(x)
my_func()

25

WRITING FUNCTIONS IN PYTHON


Closures and overwriting
x = 25 len(x.__closure__)

def foo(value):
1
def bar():
print(value)
return bar x.__closure__[0].cell_contents

x = foo(x)
25
x()

25

WRITING FUNCTIONS IN PYTHON


Definitions - nested function
Nested function: A function defined inside another function.

# outer function
def parent():
# nested function
def child():
pass
return child

WRITING FUNCTIONS IN PYTHON


Definitions - nonlocal variables
Nonlocal variables: Variables defined in the parent function that are used by the child
function.

def parent(arg_1, arg_2):


# From child()'s point of view,
# `value` and `my_dict` are nonlocal variables,
# as are `arg_1` and `arg_2`.
value = 22
my_dict = {'chocolate': 'yummy'}

def child():
print(2 * value)
print(my_dict['chocolate'])
print(arg_1 + arg_2)

return child

WRITING FUNCTIONS IN PYTHON


Closure: Nonlocal variables attached to a returned function.

def parent(arg_1, arg_2):


value = 22
my_dict = {'chocolate': 'yummy'}

def child():
print(2 * value)
print(my_dict['chocolate'])
print(arg_1 + arg_2)

return child

new_function = parent(3, 4)

print([cell.cell_contents for cell in new_function.__closure__])

[3, 4, 22, {'chocolate': 'yummy'}]

WRITING FUNCTIONS IN PYTHON


Why does all of this matter?
Decorators use:

Functions as objects

Nested functions
Nonlocal scope

Closures

WRITING FUNCTIONS IN PYTHON


Let's practice!
WRITING FUNCTIONS IN PYTHON
Decorators
WRITING FUNCTIONS IN PYTHON

Shayne Miel
Software Architect @ Duo Security
Functions

WRITING FUNCTIONS IN PYTHON


Decorators

WRITING FUNCTIONS IN PYTHON


Modify inputs

WRITING FUNCTIONS IN PYTHON


Modify outputs

WRITING FUNCTIONS IN PYTHON


Modify function

WRITING FUNCTIONS IN PYTHON


What does a decorator look like?
@double_args
def multiply(a, b):
return a * b
multiply(1, 5)

20

WRITING FUNCTIONS IN PYTHON


The double_args decorator
def multiply(a, b):
return a * b
def double_args(func):
return func
new_multiply = double_args(multiply)
new_multiply(1, 5)

multiply(1, 5)

WRITING FUNCTIONS IN PYTHON


The double_args decorator
def multiply(a, b):
return a * b
def double_args(func):
# Define a new function that we can modify
def wrapper(a, b):
# For now, just call the unmodified function
return func(a, b)
# Return the new function
return wrapper
new_multiply = double_args(multiply)
new_multiply(1, 5)

WRITING FUNCTIONS IN PYTHON


The double_args decorator
def multiply(a, b):
return a * b
def double_args(func):
def wrapper(a, b):
# Call the passed in function, but double each argument
return func(a * 2, b * 2)
return wrapper
new_multiply = double_args(multiply)
new_multiply(1, 5)

20

WRITING FUNCTIONS IN PYTHON


The double_args decorator
def multiply(a, b):
return a * b
def double_args(func):
def wrapper(a, b):
return func(a * 2, b * 2)
return wrapper
multiply = double_args(multiply)
multiply(1, 5)

20

multiply.__closure__[0].cell_contents

<function multiply at 0x7f0060c9e620>

WRITING FUNCTIONS IN PYTHON


Decorator syntax
def double_args(func): def double_args(func):
def wrapper(a, b): def wrapper(a, b):
return func(a * 2, b * 2) return func(a * 2, b * 2)
return wrapper return wrapper

@double_args
def multiply(a, b): def multiply(a, b):
return a * b return a * b

multiply = double_args(multiply)

multiply(1, 5) multiply(1, 5)

20 20

WRITING FUNCTIONS IN PYTHON


Let's practice!
WRITING FUNCTIONS IN PYTHON

You might also like