﻿ 11: Details on Functions

Nesting a Function

Introduction

As mentioned already, a function is a section of code that solves a specific problem. To make it as complete as possible, a function can use some features that are not available if you write all your code directly in the module. We will learn some of those features here.

Practical Learning: Introducing Topics on Functions

1. Start Visual Studio Code
2. To create a file, on the main menu, click File -> New File
3. Click the Select A Language link
4. Scroll down in the list of languages and click Python (python)
5. In the empty document, type the following lines:
```def show_detail(cat : str):
print("Loan Category:", cat)
print('----------------------------------')

def evaluate():
loan_amount   : float = 4750
interest_rate : float = 14.50  # %
periods       : int   = 42           # Number of months

print("Loan Amount:  ", loan_amount)
print("Interest Rate:", interest_rate)
print("Periods:      ", periods)

show_detail("Personal Loan")
print('----------------------------------')
evaluate()
print("==================================")```
6. To save the document, on the main menu, click File -> Save
7. In the Save As dialog box, select the directory you want. Click the New Folder button. Type Exercise11 and press Enter
8. Change the File Name to Exercise
9. Click Save

Creating a Nested Function

You can create a function in the body of another function. This is referred to as nesting a function. To nest a function, simply create the new function somewhere after the first line of the function. Of course, the nested function must be indented. Here is an example:

```def present():
print("I am my parent's child.");

def show():
print("I work from inside.")[;]```

Practical Learning: Introducing Else Conditions

• To nest a function, change the document as follows:
```def show_detail(cat : str):
print("Loan Category:", cat)
print('----------------------------------')

def show_applicant():
print("First Name:    Christine")
print("Last Name:     Cranston")

. . .```

Calling a Nested Function

The first function is referred to as the parent or nesting function. The function inside is referred to as the child or nested function. When you have nested a function, the inside function is hidden from outside the parent function. Therefore, the nested function can be accessed only inside the parent function. Based on this, to access the nested function, you can call it in the body of the parent function. The nested function must be called after its definition.

Practical Learning: Calling a Nested Function

1. To call a nested function, change the code as follows:
```def show_detail(cat : str):
print("Loan Category:", cat)
print('----------------------------------')

def show_applicant():
print("First Name:    Christine")
print("Last Name:     Cranston")

show_applicant();

def evaluate():
loan_amount   : float = 4750
interest_rate : float = 14.50  # %
periods       : int   = 42           # Number of months

print("Loan Amount:  ", loan_amount)
print("Interest Rate:", interest_rate)
print("Periods:      ", periods)

show_detail("Personal Loan")
print('----------------------------------')
evaluate()
print("==================================")```
2. To execute, on the main menu, click Run -> Run Without Debugging. If Visual Studio Code presents a dialog box asking you whether you trust the authors...

click Trust Workspace & Continue (if you get an error about bad indentation, it could be because you copied and pasted the code; if that happens, trying re-creating the indentations):
```Loan Category: Personal Loan
----------------------------------
First Name:    Christine
Last Name:     Cranston
----------------------------------
Loan Amount:   4750
Interest Rate: 14.5
Periods:       42
==================================
Press any key to continue . . .```

A Function as a Type

Introduction

In the Python language (but also in many other languages), a function is considered a type (or rather a first-class object). As such, one way a function can be used is as a parameter. Normally, in Python, when you create a function that uses a parameter, you simply provide a name for the parameter. Here is an example:

```def buckle_up(talk):
. . .```

In the body of the function, to use the parameter as a function, you can simply call it.

Practical Learning: Using a Function as a Type

1. To create a function as a type, change the document as follows:
```def show_detail(cat : str):
print("Loan Category:", cat)
print('----------------------------------')

def show_applicant():
print("First Name:    Christine")
print("Last Name:     Cranston")

show_applicant();

def announe():
print("Watts' A Loan is a company that provides various types of loan to persons, businesses, and organizations.")

def evaluate():
loan_amount   : float = 1750
interest_rate : float = 16.25  # %
periods       : int   = 28           # Number of months

print("Loan Amount:  ", loan_amount)
print("Interest Rate:", interest_rate)
print("Periods:      ", periods)

def prepare(intro):
print("Watts' A Loan - Welcome")
print('--------------------------------------------------------------------')
intro()

print("======================================================================")
prepare(announe)
print('--------------------------------------------------------------------')

show_detail("Personal Loan")
print('----------------------------------')
evaluate()
print("==================================")```
2. To execute the application, on the main menu, click Run -> Run Without Debugging:
```======================================================================
Watts' A Loan - Welcome
--------------------------------------------------------------------
Watts' A Loan is a company that provides various types of loan to persons, businesses, and organizations.
--------------------------------------------------------------------
Loan Category: Personal Loan
----------------------------------
First Name:    Christine
Last Name:     Cranston
----------------------------------
Loan Amount:   4750
Interest Rate: 14.5
Periods:       42
==================================
Press any key to continue . . .```

Returning a Nested Function

Earlier, we saw that you could nest a function inside another, and when you do that, the nested function cannot be accessed outside the nesting function. If you want to use the behavior of the nested function outside the nesting function, one thing you can do is to return the value of the nested function in the nesting function. To do this, somewhere in the body of the parent function before the end of its body, type return followed by the name of the nested function; don't include the parentheses.

Practical Learning: Returning a Nested Function

1. To nest a function, change the document as follows:
```def prepare(categorize):
print("Watts' A Loan - Loan Preparation")
print("--------------------------------")
categorize()

def present():
print("The company offers different types of loans.")
print('--------------------------------------------------------------------')```
2. To call the nested function in the nesting function and call the nesting function, change the document as follows:
```def prepare(categorize):
print("Watts' A Loan - Loan Preparation")
print("--------------------------------")
categorize()

def present():
print("The company offers different types of loans.")
print('--------------------------------------------------------------------')

present()

def typify():
print("Watts' A Loan provides various types of loan to persons, businesses, and organizations.")

print("====================================================================")
prepare(typify)
print("====================================================================")```
3. To execute the application, on the main menu, click Run -> Run Without Debugging:
```The company offers different types of loans.
--------------------------------------------------------------------
====================================================================
Watts' A Loan - Loan Preparation
--------------------------------
Watts' A Loan provides various types of loan to persons, businesses, and organizations.
====================================================================
Press any key to continue . . .```
4. To return the name of the function, change the nested function as follows:
```def prepare(categorize):
print("Watts' A Loan - Loan Preparation")
print("--------------------------------")
categorize()

def present():
print("The company offers different types of loans.")
print('--------------------------------------------------------------------')

return present

def typify():
print("Watts' A Loan provides various types of loan to persons, businesses, and organizations.")

print("====================================================================")
prepare(typify)
print("====================================================================")```
5. To execute the application, on the main menu, click Run -> Run Without Debugging:
```====================================================================
Watts' A Loan - Loan Preparation
--------------------------------
Watts' A Loan provides various types of loan to persons, businesses, and organizations.
====================================================================
Press any key to continue . . .```

Introduction to Decorators

Introduction

A decorator is something you want the compiler to consider or do with regards to a function (or object) in your application (many other languages such as C#, Java, Pascal, Visual Basic, etc, use features that behave like Python decorators, but they may call them by different names). Actually, a decorator is a piece of code that suggests to the compiler how to deal with a certain function (or object).

Creating a Decorator

We have already seen that a function can be nested inside another function. We mentioned that a nested function can be accessed only in the body of the nesting function. We saw that, if you are outside a nesting function, if you want to use the result of a nested function, one solution (probably the best option) is to return the name of the nested function. This feature can be used to create a decorator, a function that will assist the compiler with another function (or an object) in your application.

Before implementing the features of a decorator, you must create a nested function that its nesting function returns by name. After doing this, to create a decorator, on top of the function that will use it, type @ followed by the name of the function without parentheses and therefore without the argument. The function under that line is said to be decorated. After doing this, when you call the function that is decorated, the compiler would apply the decoration (the function that acts as the decorator) to the function.

Practical Learning: Decorating a Function

1. To decorate a function, change the code as follows:
```def prepare(categorize):
print("Watts' A Loan - Loan Preparation")
print("--------------------------------")
categorize()

def present():
print("The company offers different types of loans.")

return present

@prepare
def typify():
print("Watts' A Loan provides various types of loan to persons, businesses, and organizations.")

print("====================================================================")
typify()
print("====================================================================")```
2. To execute the application to see the result, on the main menu, click Debug -> Start Without Debugging
```Watts' A Loan - Loan Preparation
--------------------------------
Watts' A Loan provides various types of loan to persons, businesses, and organizations.
====================================================================
The company offers different types of loans.
====================================================================
Press any key to continue . . .```
3. To apply the decoration to another function, change the document as follows:
```def prepare(categorize):
print("Watts' A Loan - Loan Preparation")
print("--------------------------------")
categorize()

def present():
print("The company offers different types of loans.")

return present

@prepare
def typify():
print("Watts' A Loan provides various types of loan to persons, businesses, and organizations.")

@prepare
def contac():

@prepare
def examplify():
print("Loan Applicant")
print("Loan amount, interest rate, period")

print("====================================================================")
typify()
print('--------------------------------------------------------------------')
examplify()
print('--------------------------------------------------------------------')
contac()
print("====================================================================")```
4. To execute the application to see the result, on the main menu, click Debug -> Start Without Debugging
```Watts' A Loan - Loan Preparation
--------------------------------
Watts' A Loan provides various types of loan to persons, businesses, and organizations.
Watts' A Loan - Loan Preparation
--------------------------------
Watts' A Loan - Loan Preparation
--------------------------------
Loan Applicant
Loan amount, interest rate, period
====================================================================
The company offers different types of loans.
--------------------------------------------------------------------
The company offers different types of loans.
--------------------------------------------------------------------
The company offers different types of loans.
====================================================================
Press any key to continue . . .```