CHAPTER 4
Among computer programmers there is an important concept known as DRY: Don't Repeat Yourself. Instead of repeating several lines of code every time you want to perform a particular task, use a function that will allow you to write a block of Python code once and then use it many times. This can help reduce the overall length of your programs, as well as give you a single place to change, test, troubleshoot, and document any given task. Ultimately, this makes your application much easier to maintain in the long run.
To create a function, use the def keyword followed by the name of the function. Always follow the function name with a set of parentheses. If your function accepts parameters you may include the names of those parameters within the parentheses, separating them with commas. Finally, conclude the function definition line with a colon. The code block that follows the function definition will be executed any time the function is called. The pattern is def function_name():. The following is a very simple function.
Code Listing 121
def say_hello(): print('Hello!') |
If you were to attempt to execute this code, no output would be presented because the function is defined but never called. When calling a function you must ensure that you include the parentheses.
Code Listing 122
def say_hello(): print('Hello!') say_hello() |
Output:
Code Listing 123
Hello! |
A function will have to be defined before it can be called. Define your functions at the top of your Python program. Here you’ll see what will happen if you try to use a function that has not yet been defined.
Code Listing 124
say_hello() def say_hello(): print('Hello!') |
Output:
Code Listing 125
Traceback (most recent call last): File "say_hello.py", line 1, in <module> say_hello() NameError: name 'say_hello' is not defined |
Now let's extend the function so that it accepts a parameter. Try to think of parameters as variables that can be used inside of the function. The pattern is def function_name(parameter_name):.
Code Listing 126
def say_hello(name): print('Hello {}!'.format(name)) say_hello('Erin') say_hello('everybody') |
Output:
Code Listing 127
Hello Erin! Hello everybody! |
Once you've defined a parameter, the function will expect and require a value for that parameter. The actual value specified for a function parameter when the function is invoked is sometimes called the argument. If one is not provided you will encounter an error.
Code Listing 128
def say_hello(name): print('Hello {}!'.format(name)) say_hello() |
Output:
Code Listing 129
File "say_hello.py", line 4, in <module> say_hello() TypeError: say_hello() missing 1 required positional argument: 'name' |
If you’d like to make the parameter optional, set a default value for it by using the equals sign. The pattern is def function_name(parameter_name = default_value):.
Code Listing 130
def say_hello(name = 'there'): print('Hello {}!'.format(name)) say_hello() say_hello('Erin') |
Output:
Code Listing 131
Hello there! Hello Erin! |
Keep in mind that functions are capable of accepting multiple parameters. All you need to do is include them within the parentheses of the function definition, and separate them with a comma. When you are calling the function, always supply the arguments and separate them with commas as well.
Code Listing 132
def say_hello(first, last): print('Hello {} {}!'.format(first, last)) say_hello('Josiah', 'Carberry') |
Output:
Code Listing 133
Hello Josiah Carberry! |
When parameters are accepted by a function they can also be called positional parameters. This is because their order is important. Notice here that Josiah was assigned to first while Carberry was assigned to last. You can also explicitly pass values into a function by name. Whenever you are calling the function make sure to supply the parameter name, followed by the equal sign, and then the value for that parameter. When using named parameters, order is not important. Here's an example.
def say_hello(first, last): print('Hello {} {}!'.format(first, last)) say_hello(first = 'Josiah', last = 'Carberry') say_hello(last = 'Carberry', first = 'Hank') |
Output:
Code Listing 134
Hello Josiah Carberry! Hello Hank Carberry! |
It is also possible to combine required and optional parameters as in the following example. If you use both required and optional parameters, the required parameters should come first.
Code Listing 135
def say_hello(first, last='Carberry'): print('Hello {} {}!'.format(first, last)) say_hello('Josiah') say_hello('Hank', 'Mobley') |
Output:
Code Listing 136
Hello Josiah Carberry! Hello Hank Mobley! |
Often, the first statement of a function is a documentation string, or docstring for short. You can create a docstring by surrounding text with three double quotes. This docstring will offer a brief summary of the function. When writing the docstring make sure to ask yourself, "What does this function do?" or "Why does this function exist?" You can access this docstring by using the built-in help() function. Pass the name of the function you want more information about to help(). Type q to exit the help screen.
Code Listing 137
def say_hello(first, last='Carberry'): """Say hello.""" print('Hello {} {}!'.format(first, last)) help(say_hello) |
Output:
Code Listing 138
Help on function say_hello in module __main__: say_hello(first, last='Carberry') Say hello. |
Not only are functions capable of performing a task, they can also return data by using the return statement. This statement makes it possible for you to return any data type that you require. Once the return statement is called, no further code in the function will be executed. The following code is a function that returns a string.
Code Listing 139
def even_or_odd(number): """Determine if a number is odd or even.""" if number % 2 == 0: return 'Even' else: return 'Odd' even_or_odd_string = even_or_odd(9) print(even_or_odd_string) |
Output:
Code Listing 140
Odd |
See the following example for a similar function that returns a Boolean.
Code Listing 141
def is_odd(number): """Determine if a number is odd.""" if number % 2 == 0: return False else: return True print(is_odd(9)) |
Output:
Code Listing 142
True |
It is entirely possible for you to create functions that call other functions. The following listing is an example.
Code Listing 143
def get_name(): """Get and return a name""" name = input('What is your name? ') return name def say_name(name): """Say a name""" print('Your name is {}.'.format(name)) def get_and_say_name(): """Get and display name""" name = get_name() say_name(name) get_and_say_name() |
Output:
Code Listing 144
What is your name? Erin Your name is Erin. |
A function is a block of reusable code that can perform an action as well as optionally return data.
A function can be called only after it has been defined.
A function is defined by the basic pattern: def function_name(parameter_name):.
A function is capable of accepting parameters. To make a parameter optional simply supply a default value for that particular parameter.
You can supply a docstring as the first line of your function.
The return statement will exit the function and pass back anything that follows return.
Use the built-in help() function to get assistance with a particular object. When supplying a function to help(), the docstring enclosed within the function will be displayed.
This exercise involves creating a fill in the blank word game. Try prompting the user to enter a noun, verb, and an adjective. Use the provided responses to fill in the blanks and then display the story.
First, write a short story. Remove a noun, verb, and an adjective.
Create a function that asks for input from the user.
Create another function that will fill the blanks in the story you’ve just created.
Ensure that each function contains a docstring.
After the noun, verb, and adjective have been collected from the user, display the story that has been created using their input.
Code Listing 145
def get_word(word_class): """Get a word from standard input and return that word.""" if word_class.lower() == 'adjective': article = 'an' else: article = 'a' return input('Enter a word that is {0} {1}: '.format(article, word_class)) def fill_in_the_blanks(noun, verb, adjective): """Fills in the blanks and returns a completed story.""" story = "I never knew anyone that hadn't {1} at least once in their life, except for {2}, old Aunt Polly. She never {1}, not even when that {0} came to town.".format(noun, verb, adjective) return story def print_story(story): """Prints a story.""" print() print('Here is the story you made. Enjoy!') print() print(story) def create_story(): """Creates a story by collecting the input and printing a finished story.""" noun = get_word('noun') verb = get_word('verb') adjective = get_word('adjective') the_story = fill_in_the_blanks(noun, verb, adjective) print_story(the_story) create_story() |
Output:
Code Listing 146
Enter a word that is a noun: unicorn Enter a word that is a verb: hid Enter a word that is an adjective: vivacious Here is the story you created. Enjoy! I never knew anyone that hadn't hid at least once in their life, except for vivacious, old Aunt Polly. She never hid, not even when that unicorn came to town. |
DRY: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
Documentation for the help() built-in function: https://docs.python.org/3/library/functions.html#help
Docstring Conventions (PEP 257): http://legacy.python.org/dev/peps/pep-0257/