A function is a handy way to encasuplate a piece of logic that needs to be used again and again.
Here we use the def
keyword to define a function named say_hi
. All it does is print Hi!
to the screen.
>>> def say_hi():
... """ print a greeting """
... print('Hi!')
...
>>> say_hi()
Hi!
>>> say_hi()
Hi!
>>> say_hi()
Hi!
The general structure of a Python function definition is:
def FUNCTION_NAME(arg1, arg2, ..., kw1=v1, kw2=v2, ...):
'''EXPLANATION OF WHAT THE FUNCTION DOES'''
FUNCTION_BODY
The arg1
above are function arguments, and if a function has arguments, then the user must give a value for those arguments when calling the function. And the order of arguments is important.
The kw1
above are keywords, but they are optional because a default value v1
will be provided for each keyword. Since keywords have names, the order of the keywords isn't important.
Function names can be almost anything, but they have a few restrictions:
- contain only numbers, letters, underscores
- do not start with a number
- are not the same name as a built-in function (like
print
,list
,exit
)
Notice also that every function should have a short 1-to-5 line comment block describing what it does. This speeds up reading your code, for you and everyone else.
Let's look at some simple examples. First, we'll create a trivial function to add a couple numbers:
>>> def addnums(x, y):
... ''' Add two numbers '''
... return x + y
And now let's use the function:
>>> addnums(2, 3)
5
>>> addnums("a", "b") # Wait, what?
ab
>>> addnums("cat", 23232)
TypeError: cannot concatenate 'str' and 'int' objects
What we see is that the function works as expected for numbers, but since Python is a dynamic language, it doesn't stop you from trying to add a string
and an integer
. Of course, you can't add these, so a TypeError
is thrown. This is part of the Python "we're all consenting adults" philosophy: you are trusted to know what you're doing.
Let's see that same example with keyword arguments:
>>> def addnums(x, y=2):
''' Add two numbers, with a default value of
two for the second number.
'''
return x + y
>>> addnums(3)
5
>>> addnums(3, y=3)
6
>>> addnums(3, 3)
6
>>> addnums(3, 3, 3)
TypeError: addnums() takes at most 2 arguments (3 given)
>>> addnums("oops")
TypeError: cannot concatenate 'str' and 'int' objects
Here we see a few valid was to call the addnums
function, and a couple invalid ones. Take some time and make sure each of these cases makes sense to you.
The scope of a variable is where the name of that variable is accessable from. Inside a function, Python keeps a local variables list. Below, pi
is not modified globally, and so printing it inside and outside of the function yields two different results:
>>> pi = 1.0
>>> def set_pi():
''' set and print the value of pi '''
pi = 3.1415926
print(pi)
>>> set_pi()
3.1415926
>>> print(pi)
1.0
Variable scoping is a common source of little bugs. In Python, it is pretty easy to understand what the scope of a variable should be if you are looking for it. But for people new to the concept it takes a little time for it to become second nature.
Documentation: Just the right thing to do and Python makes it dead simple.
Docstring: the first unassigned string in a function (or class, method, program, etc.).
Here is a nice example of a helpful docstring for the function numop1
:
def numop1(x, y, multiplier=1.0, greetings="Thank you for your inquiry."):
""" Purpose: does a simple operation on two numbers.
Input: We expect x,y are numbers. multiplier is also a number
(a float is preferred) and is optional.
It defaults to 1.0. You can also specify a small greeting as a string.
Output: return x + y times the multiplier
"""
if greetings is not None:
print(greetings)
return (x + y) * multiplier
Let's write our first Python script as a stand-alone file. Leave the interpreter and create a file super_happy_fun_nums.py
. Copy the above numop1
function into that file, save and close. Then, go to the command line and run the following command:
pydoc -w super_happy_fun_nums
If that doesn't work, try:
python -m pydoc -w super_happy_fun_nums
This will generate a nicely-formmated HTML file with all the documentation for the functions in that file:
Let's take another look at the file we created above: super_happy_fun_nums.py
.
This is an example of a Python module. That is, instead of writing our Python code into the interpreter, we placed it into a text file. Certainly, you can write all of your Python code in the interpreter. But when you quit the interpreter, all of your work is lost.
Any file ending in .py is treated as a module by Python.
A module is an organized unit of Python code. Every Python file has its own global variable scope
, so you can name your variables and functions there whatever you want without conflicting with other modules.
Let's try to use the numop1
code we have saved in the super_happy_fun_nums.py
module.
You will need to be on the commandline to do this. First, navigate to the directory that contains super_happy_fun_nums.py
. Next, open up the Python intepreter by typing "python" on the commandline:
$ python
Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Now, let's import and use numop1
:
>>> from super_happy_fun_nums import numop1
>>> numop1(5, 7)
Thank you for your inquiry.
12.0
>>> numop1(2, 4, multiplier=2.5, greetings="Yo.")
Yo
15.0
Let's recap. We wrote a Python function into a file with the *.py
extension. That extension allowed the Python intepreter to know that there was importable Python code to be found. We then used "from FILENAME import THING"
to import the Python code into the intepreter and use it.
The ability to store off Python code in a module and use that code with different values is huge. This is a big step towards making Python useful to you in your every day work.
A Python program consists of one (or more) modules that are executable from the commandline. To run a Python program, just use the word python
and then the name of the file:
$ python super_happy_fun_nums.py
If you try that line above, you will see that...
Nothing happens.
Well, that's anti-climatic.
But, after all, the function numop1
above doesn't do anything until you pass it at least one number, which we didn't do. So what did you expect to happen?
It turns out, to create turn a Python module into an executable program, you need to add two things. The first is a main
function that does something:
def main():
print('Hello, World!')
Second, you need to add these two lines:
if __name__ == '__main__':
main()
If you do the above, your file will now look like:
def main():
'''Classic First Program'''
print('Hello, World!')
def numop1(x,y,multiplier=1.0,greetings="Thank you for your inquiry."):
"""
Purpose: does a simple operation on two numbers.
Input: We expect x,y are numbers. multiplier is also a number
(a float is preferred) and is optional.
It defaults to 1.0. You can also specify a small greeting as a string.
Output: return x + y times the multiplier
"""
if greetings is not None:
print(greetings)
return (x + y) * multiplier
if __name__ == '__main__':
main()
NOTE: Within a function we might leave a single blank line here and there. But I put the standard two blank lines between functions. This just makes it easier to read the code.
Okay, let's run our new script!
$ python super_happy_fun_nums.py
Hello, World!
Awesome, we just made our first Python program! But... wait, what about numop1
? Well, we didn't call that function in the main
function, so we didn't use it. That seems silly. So let's change the main method to:
def main():
'''Just printing some silly tests'''
print(numop1(2, 2))
print(numop1(3, 3, multiplier=3.3))
print(numop1(4, 4, multiplier=4, greetings='(4 + 4) * 4:'))
Let's run our program again:
$ python super_happy_fun_nums.py
Thank you for your inquiry.
4.0
Thank you for your inquiry.
19.799999999999997
(4 + 4) * 4:
32
NOW we have a real program. It has a main
function, so we can execute it from the commandline. It includes other functions that we use in main
. We have even commented our functions. This little file could serve as a blueprint for a lot of the Python work you do from now on.
Earlier, we imported numop1
into the Python interpreter by doing:
>>> from super_happy_fun_nums import numop1
If we had more than one function in super_happy_fun_nums.py
, we could import both in one of a couple ways:
>>> from super_happy_fun_nums import numop1, numop2
>>> from super_happy_fun_nums import *
A different way to import is to just import the whole module:
>>> import super_happy_fun_nums
Then, when you want to use numop1
, you have to qualify it with the module name:
>>> super_happy_fun_nums.numop1(2, 2)
So, you have options. Design your code to make it as convenient as possible for the user.
If you created another Python module and called it testing_imports.py
, you could use all of the same imports as we did in the interpreter above, to import numop1
from super_happy_fun_nums
(as long as testing_imports
and super_happy_fun_nums
are still in the same folder):
# this is a new file: testing_imports.py
from super_happy_fun_nums import numop1
def main():
print(numop1(2, 2))
if __name__ == '__main__':
main()
Now we can share code between different Python modules. That'll come in handy.
The Python moto is "batteries included". That means Python comes with all kinds of libraries (modules) built it to do a lot of things you'll want to do. We will cover some of these in more detail in a few weeks. But for now it's just good to know they exist.
An obvious first library for a scientist / engineer to know about is the math library:
>>> import math
>>> math.sqrt(4.00)
2.0
>>> math.sin(0.0)
0.0
>>> math.log(1)
0.0
>>> math.pi
3.141592653589793
Once you import math
, you can do help(math)
to learn what options are availble. Similarly, you can also do help(math.sqrt)
to learn more about something specific. If you have a question, just ask Python.
The math
library above is just the tip of the standard library iceberg. Python has all kinds of libraries built in:
- datetime - tools for dealing with dates and times
- gzip - tools for gzipping and un-gzipping files
- random - tools for generating pseudo-random numbers
- os - tools creating directories, checking if files exist, etc
- sys - add commandline arguments to your programs
- urllib2 - tools for dealing with HTTP communications over the internet
For a full list of the Python standard libraries check here.
Try this one:
import this
Today we learned about three things that will be useful in our daily work:
- Functions: a way to encapsulate code and save it for later.
- Modules: a way to save Python code into a ".py" file. Further, if you include a
main
function, you create an executable Python program. - Imports: We can now share our code between modules, and make use of Python's built-in standard libraries.