This tutorial moves very fast. If you would like a slower, more in-depth intro to Python, we suggest you take our Intro to Python Evening Course. It's the perfect way to become familiar with Python + gain experience using Python to solve challenging problems.
This web tutorial follows the Jupyter notebook found on GitHub. If you are viewing it using GitHub, then you cannot execute the cells that contain Python code. To view and run this notebook you'll need to install Jupyter on your computer before you continue. See these installation instructions for help!
Functions are an essential part of coding and are a way of defining a procedure that you can reuse. They are incredibly helpful in writing clean, readable, and reusable code. I would encourage you to code using functions (or classes) whenever you can.
Python has a very large number of built-in functions, as well as a vast repository of modules/libraries through which other functions (as well as classes) are available. Check out the built-in function docs to see all of the built-in functions that are available to use. One of the libraries whose functions I use regularly is the itertools library.
From a top-down level, functions name a piece of code that takes parameter(s) and allows you to write "tiny commands". The purpose/use of a functions should typically be able to be described in one sentence, and on average functions should probably be no longer than 10 lines.
How do I create them?
Functions are defined using a
def statement, followed by the name that you wish to give the function (this name should follow variable naming conventions -
camel_case in Python), followed by a set of parentheses that contain any potential parameters that may be passed to the function. Next, we place a colon, and then finally we get to write code for the function body. This code must fall on one or more indented lines (note that the indentation is crucial).
def my_func(passed_arg1, passed_arg2, passed_arg3): # code goes here pass
def my_func_no_args(): print 'There are no args passed :) '
def is_palindrome(word): ''' Input: String Output: Bool Return whether or not the inputted word is a palindrome. ''' # Note we use return to return something back from the function. return word == word[::-1] print is_palindrome('hello') print is_palindrome('racecar')
def get_divisors(number): ''' Input: Integer Output: List Return a list of the divisors of the inputted number ''' # The return statement can return any kind of data structure. return [divisor for divisor in xrange(1, number + 1) if number % divisor == 0] print get_divisors(10) print get_divisors(100)
[1, 2, 5, 10] [1, 2, 4, 5, 10, 20, 25, 50, 100]
Variable scope is an important concept to consider when building functions. Knowing how variable scope works will save you from many kinds of common bugs.
Variable scope determines the part (or block) of the program in which that variable is visible. We typically refer to one of two scopes of variables - global scope and local scope. A variable with global scope is visible everywhere and can be used by any function, while a variable with local scope is visible only in the function in which it was defined.
my_global_var = 'This is a global variable.' def scoping_func(): my_local_var = 'This is a local variable, only usable in the scoping_func.' print my_local_var
This is a global variable.
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-5-b0b2b2a41781> in <module>() ----> 1 print my_local_var NameError: name 'my_local_var' is not defined
This is a local variable, only usable in the scoping_func.
Variable Scope Part Two
When referencing a variable in an expression, Python will search the following scopes to resolve the reference:
1.) The current function's scope.
2.) Any enclosing scopes (like other containing functions).
3.) The scope of the module that contains the code (also called global scope).
4.) The built-in scope (contains the built-in functions).
When assigning a value to a variable, things work a little bit differently. If the variable is already defined in the current scope, then it will just take on the new value that you assign it. However, if it is not defined in the current scope, then Python treats the assignment as a variable definition. Let's take a look at how this plays out...
# This 'found' is in the global scope, so everything has access to it. found = True def find_number(numbers_lst, search_number): # This 'found' is in the scope of 'find_number', and anything that is enclosed in it. found = False def inner_func(): for num in numbers_lst: # This has access to the current function's scope and anything above it. So when # it looks for the 'found' variable, it doesn't find it in the 'innner_func' scope, # but does find it in the containing function's ('find_number') scope. Since it # find's it in the 'find_number' scope, it doesn't keep looking, and so it never # find's the one in the global scope. print found inner_func() find_number([1, 2, 3, 4, 5], 3)
False False False False False
def find_number(numbers_lst, search_number): # This 'found' is in the scope of 'find_number', and anything that is enclosed in it. found = False def inner_func(): for num in numbers_lst: if num == search_number: # With assignment, it doesn't find it in it's own scope, so it creates it. # This causes us to print True at the end of this inner function. found = True print found inner_func() return found print find_number([1, 2, 3, 4, 5], 3)
Giving parameters default values
If you'd like, you can give your function parameters default values. You do this within the function definition statement:
def find_number(numbers_lst, search_number=3): for num in numbers_lst: if num == search_number: print 'Found'
The way this works is that if the caller of your function passes in a value for search_number, the function uses that. If the caller doesn't pass in a value for search_number, then your function uses the default value that you gave it.
Note that you can also call your functions with either positional parameters (like I have done up until now), or with keyword parameters. The only stipulation is that all positional parameters must be placed before all keyword parameters (i.e. you can't call your function with a keyword parameter placed before a positional parameter).
def find_number(numbers_lst, search_number=3): for num in numbers_lst: if num == search_number: print 'Found' find_number([1, 2, 3, 4, 5]) # Okay because we specified default value. find_number([1, 2, 3, 4, 5], 4) # The second passed parameter (4) overrides the default 3. find_number([1, 2, 3, 4, 5], search_number=4) # Okay because all positional parameters specified first. find_number(numbers_lst=[1, 2, 3, 4, 5], 4) # Not okay, because we specified a keyword parameter before a positional.
File "<ipython-input-9-7fb3b12a3762>", line 9 find_number(numbers_lst=[1, 2, 3, 4, 5], 4) # Not okay, because we specified a keyword argument before a positional. SyntaxError: non-keyword arg after keyword arg
args and kwargs
The use of
**kwargs is something that you might see or use with your function. This is one of the really nice features of Python (although I don't use it often); it allows your functions to accept an arbitrary number of optional arguments.
*args allows you to accept an arbitrary of number of optional positional arguments, where as
**kwargs, which stands for keyword arguments, allows you to accept an arbitrary number of optional keyword arguments.
def args_func(first_arg, *args): print first_arg for arg in args: print arg
args_func(1, 2, 3, 4)
1 2 3 4
args_func(1, [2, 3, 4])
1 [2, 3, 4]
def kwargs_func(first_arg, **kwargs): print first_arg for kwarg, value in kwargs.iteritems(): print kwarg, value
kwargs_func(1, 2, 3, 4)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-16-6a6dffd7d4b0> in <module>() ----> 1 kwargs_func(1, 2, 3, 4) TypeError: kwargs_func() takes exactly 1 argument (4 given)
kwargs_func(1, second_arg=2, third_arg=3, fourth_arg=4)
1 second_arg 2 fourth_arg 4 third_arg 3