"* Student is able to define functions with input parameters to execute a piece of code (use functions as \"methods\")\n",
"* Student is able to define functions with input parameters to execute a piece of code (use functions as \"methods\")\n",
"* Student is able to create and use functions that return a value (or multiple values)\n",
"* Student is able to create and use functions that return a value (or multiple values)\n",
"* Student is able to import functions from libraries / modules\n",
"* Student is able to import and use functions from libraries / modules\n",
"* Student is able to use Shift-Tab to bring up the help for a function from a library\n",
"* Student is able to use Shift-Tab to bring up the help for a function from a library\n",
"* Student is able to predict if a variable name in a function refers to a local variable or a global variable\n",
"* Student is able to predict if a variable name in a function refers to a local variable or a global variable\n",
"\n",
"\n",
...
...
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
# Functions in Python
# Functions in Python
In this notebook, we will explore the implementation of functions in Python.
In this notebook, we will explore the implementation of functions in Python.
**Learning objectives for this notebook:**
**Learning objectives for this notebook:**
* Student is able to define functions with input parameters to execute a piece of code (use functions as "methods")
* Student is able to define functions with input parameters to execute a piece of code (use functions as "methods")
* Student is able to create and use functions that return a value (or multiple values)
* Student is able to create and use functions that return a value (or multiple values)
* Student is able to import functions from libraries / modules
* Student is able to import and use functions from libraries / modules
* Student is able to use Shift-Tab to bring up the help for a function from a library
* Student is able to use Shift-Tab to bring up the help for a function from a library
* Student is able to predict if a variable name in a function refers to a local variable or a global variable
* Student is able to predict if a variable name in a function refers to a local variable or a global variable
From here, the exercises get a bit more complicated. The solutions for the exercises in this notebook, and future ones, can be found at the bottom of the notebook, so that you can check your answer or have a peek if you are getting stuck.
From here, the exercises get a bit more complicated. The solutions for the exercises in this notebook, and future ones, can be found at the bottom of the notebook, so that you can check your answer or have a peek if you are getting stuck.
## Functions to save typing
## Functions to save typing
In programming, you often want to repeat the same sequence of commands over and over again.
In programming, you often want to repeat the same sequence of commands over and over again.
One way to do this is to copy and paste the same piece of code over and over again. This is actually quite easy, but runs quickly into a problem: let's say you want to change a little bit what that code will do, then you need to change it in many places. If you change it in one place but forget in another, then your program might crash (ie. give an error). Or even worse, and even harder to <ahref=https://en.wikipedia.org/wiki/Debugging>debug</a> the mistake may may give an error message but give you the wrong answer!
One way to do this is to copy and paste the same piece of code over and over again. This is actually quite easy, but runs quickly into a problem: let's say you want to change a little bit what that code will do, then you need to change it in many places. If you change it in one place but forget in another, then your program might crash (ie. give an error). Or even worse, and even harder to <ahref=https://en.wikipedia.org/wiki/Debugging>debug</a> the mistake may may give an error message but give you the wrong answer!
For this reason (among others), programming languages allow programmers to define "functions". Functions are pieces of code that you can give a name and then enable you to them use over and over again, without having to retype the code text.
For this reason (among others), programming languages allow programmers to define "functions". Functions are pieces of code that you can give a name and then enable you to them use over and over again, without having to retype the code text.
As an example, let's say that we want to print out the value of a variables named `a` and `b` using a long sentence:
As an example, let's say that we want to print out the value of a variables named `a` and `b` using a long sentence:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
a=6
a=6
b=4
b=4
print("The value of variable a is",a)
print("The value of variable a is",a)
print("The value of variable b is",b)
print("The value of variable b is",b)
a=a/2
a=a/2
b=3
b=3
print("The value of variable a is",a)
print("The value of variable a is",a)
print("The value of variable b is",b)
print("The value of variable b is",b)
a=a+1
a=a+1
b=1.5
b=1.5
print("The value of variable a is",a)
print("The value of variable a is",a)
print("The value of variable b is",b)
print("The value of variable b is",b)
a=a-20
a=a-20
b=-1e4
b=-1e4
print("The value of variable a is",a)
print("The value of variable a is",a)
print("The value of variable b is",b)
print("The value of variable b is",b)
a=a+1j
a=a+1j
b=1
b=1
print("The value of variable a is",a)
print("The value of variable a is",a)
print("The value of variable b is",b)
print("The value of variable b is",b)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
To save a lot of typing, one can define a simple function to do this work for us. To define a function, you use the following syntax:
To save a lot of typing, one can define a simple function to do this work for us. To define a function, you use the following syntax:
```
```
def function_name():
def function_name():
...
...
```
```
Here, you replace the `...` with the code you want to function to execute. The Python the code inside the function should be <ahref=https://en.wikipedia.org/wiki/Indentation_(typesetting)>indented</a> by starting each line with a <ahref=https://en.wikipedia.org/wiki/Tab_key>tab</a>. By default, adding a tab will produce 4 spaces in your code. You can also "indent" your code by manually adding spaces, but you must make sure to add 4 spaces each time. The Jupyter notebook will try to detect if you make a mistake in your indentation, and will sometimes color your text in red if it detects a mistake.
Here, you replace the `...` with the code you want to function to execute. The Python the code inside the function should be <ahref=https://en.wikipedia.org/wiki/Indentation_(typesetting)>indented</a> by starting each line with a <ahref=https://en.wikipedia.org/wiki/Tab_key>tab</a>. By default, adding a tab will produce 4 spaces in your code. You can also "indent" your code by manually adding spaces, but you must make sure to add 4 spaces each time. The Jupyter notebook will try to detect if you make a mistake in your indentation, and will sometimes color your text in red if it detects a mistake.
Tabs in Python are VERY IMPORTANT: python uses tabs to know which code is inside the function and which is not. If you make a mistake with the tabs in such a way that python cannot understand what you mean, it will give you an `IdentationError`.
Tabs in Python are VERY IMPORTANT: python uses tabs to know which code is inside the function and which is not. If you make a mistake with the tabs in such a way that python cannot understand what you mean, it will give you an `IdentationError`.
In notebooks, you can also select a line, or multiple lines, and then use `Tab` to increase their indentation level, or use `Shift-Tab` to decrease their indentation level.
In notebooks, you can also select a line, or multiple lines, and then use `Tab` to increase their indentation level, or use `Shift-Tab` to decrease their indentation level.
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
deftest_tab_and_shift_tab():
deftest_tab_and_shift_tab():
somecode
somecode
thatisindendented
thatisindendented
tryselectingthistext
tryselectingthistext
andthenpushingtab
andthenpushingtab
andshift-tab
andshift-tab
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
Once you have defined your function, you can execute it by using the code `function_name()`.
Once you have defined your function, you can execute it by using the code `function_name()`.
Let's look at how to use a function as a "procedure" to simplify the code above:
Let's look at how to use a function as a "procedure" to simplify the code above:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defprint_status():
defprint_status():
print("The value of variable a is",a)
print("The value of variable a is",a)
print("The value of variable b is",b)
print("The value of variable b is",b)
a=6
a=6
b=4
b=4
print_status()
print_status()
a=a/2
a=a/2
b=3
b=3
print_status()
print_status()
a=a+1
a=a+1
b=1.5
b=1.5
print_status()
print_status()
a=a-20
a=a-20
b=-1e4
b=-1e4
print_status()
print_status()
a=a+1j
a=a+1j
b=1
b=1
print_status()
print_status()
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
In this example, it may not be such a big deal, but you can imagine that as the code in your function becomes more and more complicated, it will save you a lot of time. Also, imagine that I wanted to change the wording of the sentence I print: in the case with the function, I would only have to do this once, while in the example without function, I would have to manually change this at 5 different places.
In this example, it may not be such a big deal, but you can imagine that as the code in your function becomes more and more complicated, it will save you a lot of time. Also, imagine that I wanted to change the wording of the sentence I print: in the case with the function, I would only have to do this once, while in the example without function, I would have to manually change this at 5 different places.
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.1** Write your own function that contains two lines of code. The first line should make a new variable `var2` that is `var` converted to an integer. The second line of your code should print the value of `var2`.
**Exercise 2.1** Write your own function that contains two lines of code. The first line should make a new variable `var2` that is `var` converted to an integer. The second line of your code should print the value of `var2`.
Using this code, play around with the indentation (add extra tabs and spaces for example) to see how 'critical' Python is with indentation. For example: does three spaces work instead of `Tab`? Does one space work? What about `Tab` on the first line and three spaces on the second line? Can you make Python trigger an `IdentationError`?
Using this code, play around with the indentation (add extra tabs and spaces for example) to see how 'critical' Python is with indentation. For example: does three spaces work instead of `Tab`? Does one space work? What about `Tab` on the first line and three spaces on the second line? Can you make Python trigger an `IdentationError`?
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
var=3.5
var=3.5
# Your function here
# Your function here
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
## Functions with input variables
## Functions with input variables
Let's say that we wanted to print out the status of variables that we do not know the name of ahead of time, as in the example above. Say we wanted to make a function that could print out a message with the status of value of ANY variable. How could we do this?
Let's say that we wanted to print out the status of variables that we do not know the name of ahead of time, as in the example above. Say we wanted to make a function that could print out a message with the status of value of ANY variable. How could we do this?
In the example above, our function explicitly printed out variables `a` and `b`. But this only works because I know in advance that the person using my function has defined variables `a` and `b`. But what if I want to print the value of variable `c`?
In the example above, our function explicitly printed out variables `a` and `b`. But this only works because I know in advance that the person using my function has defined variables `a` and `b`. But what if I want to print the value of variable `c`?
To allow functions to be more generic, and therefore more "reusable" in general, Python allows you to define "input variables" for your function. The syntax for this is the following:
To allow functions to be more generic, and therefore more "reusable" in general, Python allows you to define "input variables" for your function. The syntax for this is the following:
```
```
def function_name(x):
def function_name(x):
...
...
```
```
When you do this, for the code INSIDE your function, a variable `x` will be defined that will have the value given by the input value given to the function by the user. Let's look at a specific example:
When you do this, for the code INSIDE your function, a variable `x` will be defined that will have the value given by the input value given to the function by the user. Let's look at a specific example:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defprint_status2(x):
defprint_status2(x):
print("The value passed to the function is",x)
print("The value passed to the function is",x)
a=1.5
a=1.5
print_status2(a)
print_status2(a)
a=1+1j
a=1+1j
print_status2(a)
print_status2(a)
print_status2(1.5323)
print_status2(1.5323)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
How does this work?
How does this work?
When the function `print_status(a)` is called, Python "sends" ("passes" in computer speak) the value of `a` to the function. Inside the function, Python creates a new (temporary) variable called `x`, that is defined ONLY while the function code is running. This temporary variable `x` is then assigned the value that was sent to the function, and then the code is executed. When the function is finished, the variable `x` is destroyed. (Try adding the code `print(x)` above outside the function and see what happens!)
When the function `print_status(a)` is called, Python "sends" ("passes" in computer speak) the value of `a` to the function. Inside the function, Python creates a new (temporary) variable called `x`, that is defined ONLY while the function code is running. This temporary variable `x` is then assigned the value that was sent to the function, and then the code is executed. When the function is finished, the variable `x` is destroyed. (Try adding the code `print(x)` above outside the function and see what happens!)
Note, as you can see in the third example, the things you pass to functions do not even need to be variables! This is fine because the function only needs the value of the argument that is passed to the function.
Note, as you can see in the third example, the things you pass to functions do not even need to be variables! This is fine because the function only needs the value of the argument that is passed to the function.
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.2** Copy your code from exercise 2.1 (but then with just normal indentation using tabs) into the cell below and change it such that it uses a function with input parameters to achieve the same task.
**Exercise 2.2** Copy your code from exercise 2.1 (but then with just normal indentation using tabs) into the cell below and change it such that it uses a function with input parameters to achieve the same task.
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your code here
# Your code here
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
## Functions with multiple inputs
## Functions with multiple inputs
Functions can also take multiple input variables. To do this, you put them all in between the brackets `()`, separated by commas. For example, with 3 variables, the syntax is:
Functions can also take multiple input variables. To do this, you put them all in between the brackets `()`, separated by commas. For example, with 3 variables, the syntax is:
You would then use this function in the following way:
You would then use this function in the following way:
```
```
function_name(argument1, argument2, argument3)
function_name(argument1, argument2, argument3)
```
```
When you do this, inside the function, `variable1` will get assigned the value of `argument1`, `variable2` will get assigned the value of `argument2`, and `variable3` will get assigned the value of `argument3`. This matching of the position in the list is called matching by "positional order".
When you do this, inside the function, `variable1` will get assigned the value of `argument1`, `variable2` will get assigned the value of `argument2`, and `variable3` will get assigned the value of `argument3`. This matching of the position in the list is called matching by "positional order".
Note that there are several different names used for the "input variables" of a function: often, computer scientists will also use the name "input arguments" (or just "arguements), or "input parameters" (or just "parameters").
Note that there are several different names used for the "input variables" of a function: often, computer scientists will also use the name "input arguments" (or just "arguements), or "input parameters" (or just "parameters").
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defprint_status3(x,y):
defprint_status3(x,y):
print("The value of the first input variable is ",x)
print("The value of the first input variable is ",x)
print("The value of the second input variable is ",y)
print("The value of the second input variable is ",y)
print_status3(1,2)
print_status3(1,2)
print_status3(2.5,1.5)
print_status3(2.5,1.5)
print_status3(a,2*a)
print_status3(a,2*a)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.3** Make a new function `print_status4()` that takes three variables as arguments and prints out messages telling the user the values of each of them (as above, but with three input variables). Test it to make sure it works.
**Exercise 2.3** Make a new function `print_status4()` that takes three variables as arguments and prints out messages telling the user the values of each of them (as above, but with three input variables). Test it to make sure it works.
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your code here
# Your code here
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
## Functions that return a value
## Functions that return a value
In addition to receiving values as inputs, functions can also send back values to the person using the function. In computer programming, this is called the "return value".
In addition to receiving values as inputs, functions can also send back values to the person using the function. In computer programming, this is called the "return value".
When you create a function, you can use the `return` command to specify what value should be sent back to the person using the function. Let's look at an example:
When you create a function, you can use the `return` command to specify what value should be sent back to the person using the function. Let's look at an example:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defmy_formula(x):
defmy_formula(x):
y=x**2+3
y=x**2+3
returny
returny
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
To "capture" the value returned by the function, you can assign it to a varible like this:
To "capture" the value returned by the function, you can assign it to a varible like this:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
result=my_formula(3.5)
result=my_formula(3.5)
print(result)
print(result)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
You can also just directly "use" the result of the function if you want:
You can also just directly "use" the result of the function if you want:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
print(my_formula(4.6))
print(my_formula(4.6))
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
Note that as soon as python sees the `return` command, it stops running the function, so any code after it will not be executed:
Note that as soon as python sees the `return` command, it stops running the function, so any code after it will not be executed:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defmyfunction(x):
defmyfunction(x):
print("This gets printed.")
print("This gets printed.")
returnx**2+3
returnx**2+3
print("This does not.")
print("This does not.")
print(myfunction(5))
print(myfunction(5))
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
If you want to send back more than one result to the user of your function, you can separate the results with commas when you use the `return` command. How do you make use of these two variables that you send back? You will explore this in this exercise:
If you want to send back more than one result to the user of your function, you can separate the results with commas when you use the `return` command. How do you make use of these two variables that you send back? You will explore this in this exercise:
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.4****(a)** Write a function that takes two real numbers as input and returns the sum and product of the two numbers. In your function, try to send *both* of the calculated numbers back as a return value. We have not taught you that yet so you will have to look it up: I recommend trying a google search for "python function return two variables".
**Exercise 2.4****(a)** Write a function that takes two real numbers as input and returns the sum and product of the two numbers. In your function, try to send *both* of the calculated numbers back as a return value. We have not taught you that yet so you will have to look it up: I recommend trying a google search for "python function return two variables".
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your function here
# Your function here
defproduct_and_sum(...):
defproduct_and_sum(...):
...
...
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**(b)** Now USE your function to calculate the sum and product of `a` and `b`, "capturing" the sum and product in variables `s` and `p`:
**(b)** Now USE your function to calculate the sum and product of `a` and `b`, "capturing" the sum and product in variables `s` and `p`:
One of the big advantages of python is that there are huge collection of libraries that include code for doing a huge number of things for you! We will make extensive use of the library `numpy` for numerical calculations in Python, and the library `matplotlib` for generating scientific plots. Beyond this, nearly anything you want to be able to do on a computer can be found in Python libraries, which is one of the reasons it is so popular.
One of the big advantages of python is that there are huge collection of libraries that include code for doing a huge number of things for you! We will make extensive use of the library `numpy` for numerical calculations in Python, and the library `matplotlib` for generating scientific plots. Beyond this, nearly anything you want to be able to do on a computer can be found in Python libraries, which is one of the reasons it is so popular.
In order make use of these libraries of code, you need to "import" them into the "namespace" of your kernel.
In order make use of these libraries of code, you need to "import" them into the "namespace" of your kernel.
("Namespace" is Python-speak for the list of functions and variable names that you can find in the running copy of python that is connected to your notebook.)
("Namespace" is Python-speak for the list of functions and variable names that you can find in the running copy of python that is connected to your notebook.)
Here, we will show you a few examples of different ways of importing code into your notebook from a library (also called a "module"). For this, we will take the example we used already in Notebook 1: in the module `time`, there is a function called `sleep()` that will perform the task of "pausing" for a number of seconds given by the its argument.
Here, we will show you a few examples of different ways of importing code into your notebook from a library (also called a "module"). For this, we will take the example we used already in Notebook 1: in the module `time`, there is a function called `sleep()` that will perform the task of "pausing" for a number of seconds given by the its argument.
You can find out more about the `time` module by looking at its documentation webpage:
You can find out more about the `time` module by looking at its documentation webpage:
https://docs.python.org/3/library/time.html
https://docs.python.org/3/library/time.html
and specifically about the `sleep()` function here:
and specifically about the `sleep()` function here:
The simplest way to be able use the `sleep` function of the `time` module is to import it using the following command:
The simplest way to be able use the `sleep` function of the `time` module is to import it using the following command:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
importtime
importtime
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
You can see it has been imported by using the `%whos` command:
You can see it has been imported by using the `%whos` command:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
%whos
%whos
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
Once it has been imported, you can access all the functions of the module by adding `time.` in front of the function name (from the time module) in your code:
Once it has been imported, you can access all the functions of the module by adding `time.` in front of the function name (from the time module) in your code:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
print("Starting to sleep")
print("Starting to sleep")
time.sleep(5)
time.sleep(5)
print("Done!")
print("Done!")
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
If you import the whole module, you will have access to all the functions in it. To see what functions are in the module for you to use type `dir(time)`, which will generate this list.
If you import the whole module, you will have access to all the functions in it. To see what functions are in the module for you to use type `dir(time)`, which will generate this list.
Sometimes, if you will be using the functions from the module a lot, you can give it a different "prefix" to save yourself some typing:
Sometimes, if you will be using the functions from the module a lot, you can give it a different "prefix" to save yourself some typing:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
importtimeastm
importtimeastm
print("Starting to sleep")
print("Starting to sleep")
tm.sleep(5)
tm.sleep(5)
print("Done!")
print("Done!")
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
We will use this a lot when using the `numpy` module, shortening its name to `np` when we import it, and also for the `matplotlib.pyplot` submodule, which we will shorten to `plt`. (These are also typically used conventions in the scientific community.)
We will use this a lot when using the `numpy` module, shortening its name to `np` when we import it, and also for the `matplotlib.pyplot` submodule, which we will shorten to `plt`. (These are also typically used conventions in the scientific community.)
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
### Importing a single function
### Importing a single function
If you need only a single function from a library, there is also a second commonly used way to import only that single function using the following syntax:
If you need only a single function from a library, there is also a second commonly used way to import only that single function using the following syntax:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
fromtimeimportsleep
fromtimeimportsleep
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
When you do this, the function `sleep()` will be available directly in your notebook kernel "namespace" without any prefix:
When you do this, the function `sleep()` will be available directly in your notebook kernel "namespace" without any prefix:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
print("Starting to sleep")
print("Starting to sleep")
sleep(5)
sleep(5)
print("Done!")
print("Done!")
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
Using `%whos`, we can now see that we have three different ways to use the `sleep()` function:
Using `%whos`, we can now see that we have three different ways to use the `sleep()` function:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
%whos
%whos
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
If you look around on the internet, you will also find people that will do the following
If you look around on the internet, you will also find people that will do the following
```
```
from numpy import *
from numpy import *
```
```
This will import all the functions from numpy directly into the namespace of your kernel with no prefix. You might think: what a great idea, this will save me loads of typing! Instead of typing `np.sqrt()` for example, to use the square-root function, I could just type `sqrt()`.
This will import all the functions from numpy directly into the namespace of your kernel with no prefix. You might think: what a great idea, this will save me loads of typing! Instead of typing `np.sqrt()` for example, to use the square-root function, I could just type `sqrt()`.
While true, it will save typing, it also comes with a risk: sometimes different modules have functions that have the same name, but do different things. A concrete example is the function `sqrt()`, which is available in both the `math` module and the `numpy` module. Unfortunately, `math.sqrt()` will give an error when using numpy arrays (which we will learn more about in later notebooks).
While true, it will save typing, it also comes with a risk: sometimes different modules have functions that have the same name, but do different things. A concrete example is the function `sqrt()`, which is available in both the `math` module and the `numpy` module. Unfortunately, `math.sqrt()` will give an error when using numpy arrays (which we will learn more about in later notebooks).
If you import both of them, you will overwrite these functions by the second import, and if you're not careful, you will forget which one you are using, and it could cause your code to break. It will also "crowd" your notebooks namespace: using the `whos` function, you will suddenly see hundreds or even thousands of functions, instead of only just a module.
If you import both of them, you will overwrite these functions by the second import, and if you're not careful, you will forget which one you are using, and it could cause your code to break. It will also "crowd" your notebooks namespace: using the `whos` function, you will suddenly see hundreds or even thousands of functions, instead of only just a module.
For these reasons, it is generally advised not to use `import *`, and it is considered poor coding practice in modern python.
For these reasons, it is generally advised not to use `import *`, and it is considered poor coding practice in modern python.
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
### Shift-Tab for getting help
### Shift-Tab for getting help
Like the tab completion we saw in the first notebook, Jupyter also can give you help on functions you have imported from libraries if you type `Shift-Tab`.
Like the tab completion we saw in the first notebook, Jupyter also can give you help on functions you have imported from libraries if you type `Shift-Tab`.
Say I forgot how to use the `sleep()` function. If I type the word "sleep" and then push `Shift-Tab`, Jupyter will bring up a help window for that function.
Say I forgot how to use the `sleep()` function. If I type the word "sleep" and then push `Shift-Tab`, Jupyter will bring up a help window for that function.
Try it: click on any part of the word `sleep` in the following code cell and push `Shift-Tab`:
Try it: click on any part of the word `sleep` in the following code cell and push `Shift-Tab`:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
sleep
sleep
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
You can also find the same help as the output of a code cell by using the `help()` function:
You can also find the same help as the output of a code cell by using the `help()` function:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
help(sleep)
help(sleep)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
There are extensive online resources for many modules. The most used modules have helpful examples on the functions and how to implement them.
There are extensive online resources for many modules. The most used modules have helpful examples on the functions and how to implement them.
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.5 (a)** Find help for the built-in functions `abs`, `int`, and `input`. Which of the help functions are easy to read? Which one does not provide such useful information (compared to the online documentation page)? (Put each help command in a separate cell)
**Exercise 2.5 (a)** Find help for the built-in functions `abs`, `int`, and `input`. Which of the help functions are easy to read? Which one does not provide such useful information (compared to the online documentation page)? (Put each help command in a separate cell)
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your code here
# Your code here
```
```
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your code here
# Your code here
```
```
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your code here
# Your code here
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**(b)** Import the function `glob` from the library `glob` and print its help information. What does the function `glob("../*")` do?
**(b)** Import the function `glob` from the library `glob` and print its help information. What does the function `glob("../*")` do?
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# run the help here
# run the help here
```
```
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# your code here
# your code here
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
## Global variables, local variables, and variable scope
## Global variables, local variables, and variable scope
In our first functions above, we saw a couple of examples of using variables inside functions.
In our first functions above, we saw a couple of examples of using variables inside functions.
In the first example, we used the variables `a` and `b` inside our function that we created outside our function, directly in our notebook.
In the first example, we used the variables `a` and `b` inside our function that we created outside our function, directly in our notebook.
In the second example, we used the "temporary" variable `x` inside our function.
In the second example, we used the "temporary" variable `x` inside our function.
These were two examples of different variable "scope". In computer programming, <ahref=https://en.wikipedia.org/wiki/Scope_(computer_science)>scope</a> define the rules Python uses when it tries to look up the value of a variable.
These were two examples of different variable "scope". In computer programming, <ahref=https://en.wikipedia.org/wiki/Scope_(computer_science)>scope</a> define the rules Python uses when it tries to look up the value of a variable.
In the slightly simplified picture we will work with here, variables can have two different types of "scopes": **global scope** and **local scope**.
In the slightly simplified picture we will work with here, variables can have two different types of "scopes": **global scope** and **local scope**.
If Python looks for a variable value, it first looks in the local scope (also called "local namespace"). If it does not find it, python will go up into the global scope (also called the "global namespace") and look for the variable there. If it does not find the varible there, it will trigger an error (a `NameError` to be precise).
If Python looks for a variable value, it first looks in the local scope (also called "local namespace"). If it does not find it, python will go up into the global scope (also called the "global namespace") and look for the variable there. If it does not find the varible there, it will trigger an error (a `NameError` to be precise).
How do I create a global variable? By default, if you create a variable directly in your notebook (and not in a function in your notebook), it will always be **global**. So, actually, you've already created a bunch of global variables!
How do I create a global variable? By default, if you create a variable directly in your notebook (and not in a function in your notebook), it will always be **global**. So, actually, you've already created a bunch of global variables!
Any variables you define inside a function in your code will be a **local** variable (including the input variables automatically created if your function takes any arguments).
Any variables you define inside a function in your code will be a **local** variable (including the input variables automatically created if your function takes any arguments).
If you want to create a global variable inside a function, or make sure the variable you are referring to is the global variable and not the local one, you can do this by the `global` qualifier, which we will look at in a minute.
If you want to create a global variable inside a function, or make sure the variable you are referring to is the global variable and not the local one, you can do this by the `global` qualifier, which we will look at in a minute.
Let's take a look at this in more detail by analysing a few examples.
Let's take a look at this in more detail by analysing a few examples.
**Example 1** Accessing a global variable inside a function
**Example 1** Accessing a global variable inside a function
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
a1=5
a1=5
defmy_func():
defmy_func():
print(a1)
print(a1)
my_func()
my_func()
a1=6
a1=6
my_func()
my_func()
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
In this example, when Python is inside the function `my_func()`, it first looks to see if there is a variable `a1` in the local scope of the function. It does not find one, so it then goes and looks in the global scope. There, it finds a variable `a1`, and so it uses this one.
In this example, when Python is inside the function `my_func()`, it first looks to see if there is a variable `a1` in the local scope of the function. It does not find one, so it then goes and looks in the global scope. There, it finds a variable `a1`, and so it uses this one.
**Example 2** An example that doesn't work (unless you've run the next cell, in which case it will only fail again after you restart your kernel)
**Example 2** An example that doesn't work (unless you've run the next cell, in which case it will only fail again after you restart your kernel)
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defmy_func():
defmy_func():
print(b1)
print(b1)
my_func()
my_func()
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
This code gives a `NameError` because there is no variable `b1` yet created in the global scope. If we run the following code cell and try the code above again, it will work.
This code gives a `NameError` because there is no variable `b1` yet created in the global scope. If we run the following code cell and try the code above again, it will work.
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
b1=6
b1=6
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
Here you can see one of risks of languages like python: because of the persistent memory of the kernel, code can succeed or fail depending on what code you have run before it...
Here you can see one of risks of languages like python: because of the persistent memory of the kernel, code can succeed or fail depending on what code you have run before it...
If you want to see the error message above again, you can delete variable b1 using this code and run it again:
If you want to see the error message above again, you can delete variable b1 using this code and run it again:
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
delb1
delb1
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Example 3** Variables defined in the local scope of a function are not accessible outside the function
**Example 3** Variables defined in the local scope of a function are not accessible outside the function
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defmy_func():
defmy_func():
x=5
x=5
my_func()
my_func()
print(x)
print(x)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Example 4** Variables passed to functions cannot be modified by the function (more on this later when we look at more complicated data structures...sometimes this is different)
**Example 4** Variables passed to functions cannot be modified by the function (more on this later when we look at more complicated data structures...sometimes this is different)
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defmy_func(a):
defmy_func(a):
a=6
a=6
a=5
a=5
my_func(a)
my_func(a)
print(a)
print(a)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
This one is a bit subtle (mega-confusing?) because we re-used the same name `a` for the local variable in the function as the global variable outside of the function. However, the operation is quite logical. When the function code starts running, it creates a `local` variable `a` to store the value it received. And now, because there is already a local variable called `a`, using `a` in the function refers to the `local` variable `a`, not the `global` variable `a` we define before calling the function.
This one is a bit subtle (mega-confusing?) because we re-used the same name `a` for the local variable in the function as the global variable outside of the function. However, the operation is quite logical. When the function code starts running, it creates a `local` variable `a` to store the value it received. And now, because there is already a local variable called `a`, using `a` in the function refers to the `local` variable `a`, not the `global` variable `a` we define before calling the function.
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Example 5** This one is a tricky one.
**Example 5** This one is a tricky one.
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
a=6
a=6
defmy_func():
defmy_func():
a=7
a=7
print(a)
print(a)
my_func()
my_func()
print(a)
print(a)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
It would seem that the function would refer to the global variable `a` and therefore change it's value. However, it is tricky since we first use `a` in the function in an assignment. An assignment in python will automatically create a variable if it does not exist, and so python creates a new variable named `a` in the local scope. The name `a` inside the function now refers to this newly created local variable, and therefore the global variable will not be changed. In fact, this guarantees that you cannot change global variables inside a function, unless you use the `global` qualifier shown in the next example.
It would seem that the function would refer to the global variable `a` and therefore change it's value. However, it is tricky since we first use `a` in the function in an assignment. An assignment in python will automatically create a variable if it does not exist, and so python creates a new variable named `a` in the local scope. The name `a` inside the function now refers to this newly created local variable, and therefore the global variable will not be changed. In fact, this guarantees that you cannot change global variables inside a function, unless you use the `global` qualifier shown in the next example.
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Example 6** If you want to make sure that the `a` inside your function is referring to the global variable `a`, you can include the line `global a` inside your function to tell python that you mean the global variable `a`.
**Example 6** If you want to make sure that the `a` inside your function is referring to the global variable `a`, you can include the line `global a` inside your function to tell python that you mean the global variable `a`.
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
a=6
a=6
defmy_func():
defmy_func():
globala
globala
a=7
a=7
print(a)
print(a)
my_func()
my_func()
print(a)
print(a)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
Note that in general, it is considered bad programming practice to use (too many) global variables. Why? When you write longer and bigger sections of code, it is easier to understand what is going in in your function if your function uses only local variables and communicates back and forth using input parameter and return variables. Using too many global variables in a function can be confusing because they are defined in a different place in your code and so you don't have a good oversight of them. (Bigger projects can easily have 10,000+ lines of code!)
Note that in general, it is considered bad programming practice to use (too many) global variables. Why? When you write longer and bigger sections of code, it is easier to understand what is going in in your function if your function uses only local variables and communicates back and forth using input parameter and return variables. Using too many global variables in a function can be confusing because they are defined in a different place in your code and so you don't have a good oversight of them. (Bigger projects can easily have 10,000+ lines of code!)
In computer science, this is a topic of often intense debate (resulting in what nerds refer to as a <ahref="https://www.urbandictionary.com/define.php?term=flame%20war">flame war</a>), with global variables being branded as "dangerous" like in this stack exchange post:
In computer science, this is a topic of often intense debate (resulting in what nerds refer to as a <ahref="https://www.urbandictionary.com/define.php?term=flame%20war">flame war</a>), with global variables being branded as "dangerous" like in this stack exchange post:
But I personally agree with the comments in this post that "global variables have their place but should be used sparingly".
But I personally agree with the comments in this post that "global variables have their place but should be used sparingly".
Summary of the rules for global and local variables:
Summary of the rules for global and local variables:
* If a local variable of the same name exists or is created by python (by assignment, for example), then python uses the local varible
* If a local variable of the same name exists or is created by python (by assignment, for example), then python uses the local varible
* If you try to use a variable name that does not exist locally, python checks for a global variable of the same name
* If you try to use a variable name that does not exist locally, python checks for a global variable of the same name
* If you want to change the value of a global inside a function, then you must use the `global` statement to make it clear to python than you want that name to refer to the global variable
* If you want to change the value of a global inside a function, then you must use the `global` statement to make it clear to python than you want that name to refer to the global variable
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
## Solutions to Exercises
## Solutions to Exercises
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.1**
**Exercise 2.1**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
var=3.5
var=3.5
# Example: one space is actually enough! But is discouraged, as you can see
# Example: one space is actually enough! But is discouraged, as you can see
# by the fact the the notebook made it red colored.
# by the fact the the notebook made it red colored.
defmyfunction():
defmyfunction():
var2=int(var)
var2=int(var)
print(var2)
print(var2)
# Once you've started a code block though with a specific indentaton, then you cant change
# Once you've started a code block though with a specific indentaton, then you cant change
# it anymore.
# it anymore.
defmyfunction():
defmyfunction():
var2=int(var)
var2=int(var)
print(var2)
print(var2)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.2**
**Exercise 2.2**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defmyfunction(var):
defmyfunction(var):
var2=int(var)
var2=int(var)
print(var2)
print(var2)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.3**
**Exercise 2.3**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
defprint_status3(x,y,z):
defprint_status3(x,y,z):
print("The value of the first input variable is ",x)
print("The value of the first input variable is ",x)
print("The value of the second input variable is ",y)
print("The value of the second input variable is ",y)
print("The value of the second input variable is ",z)
print("The value of the second input variable is ",z)
print(1,2,3)
print(1,2,3)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.4****(a)**
**Exercise 2.4****(a)**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
# Your function here
# Your function here
defproduct_and_sum(a,b):
defproduct_and_sum(a,b):
returna*b,a+b
returna*b,a+b
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**(b)**
**(b)**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
a=1.5
a=1.5
b=2.5
b=2.5
p,s=product_and_sum(a,b)
p,s=product_and_sum(a,b)
print("Sum is:",s)
print("Sum is:",s)
print("Product is:",p)
print("Product is:",p)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**Exercise 2.5****(a)**
**Exercise 2.5****(a)**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
help(abs)
help(abs)
```
```
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
help(int)
help(int)
```
```
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
help(input)
help(input)
```
```
%% Cell type:markdown id: tags:
%% Cell type:markdown id: tags:
**(b)**
**(b)**
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
fromglobimportglob
fromglobimportglob
help(glob)
help(glob)
```
```
%% Cell type:code id: tags:
%% Cell type:code id: tags:
``` python
``` python
glob("../*")
glob("../*")
# It returns list of files and folders in the parent directory of that
# It returns list of files and folders in the parent directory of that