.. Copyright Gareth McCaughan and Jeffrey Elkner. All rights reserved. CONDITIONS: A "Transparent" form of a document means a machine-readable form, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A form that is not Transparent is called "Opaque". Examples of Transparent formats include LaTeX source and plain text. Examples of Opaque formats include PDF and Postscript. Paper copies of a document are considered to be Opaque. Redistribution and use of this document in Transparent and Opaque forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of this document in Transparent form must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions of this document in Opaque form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution, and reproduce the above copyright notice in the Opaque document itself. - Neither the name of Scripture Union, nor LiveWires nor the names of its contributors may be used to endorse or promote products derived from this document without specific prior written permission. DISCLAIMER: THIS DOCUMENT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, CONTRIBUTORS OR SCRIPTURE UNION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Functions ========= Introduction ------------ A *function* is just a piece of Python program with a name. Functions are very important; this sheet tells you all about functions in Python. What's a function? ------------------ A function is like a recipe. It's a set of instructions that you can refer to by name. Using functions saves thinking, in the same sort of way as using recipes does; if you're planning a meal it's much easier if you can just say We'll have spaghetti bolognaise and apple crumble rather than having to plan every detail of the meal from first principles . Functions are useful when you want to do the same thing several times: you just **define** a function once (like writing down a recipe) and then use it several times (like making several cakes with the same recipe). You use a function by making a **function call**. A function call looks like the first line of the function definition except you don't put the colon (``:``) at the end. Functions are even more useful when you want to do *almost* the same thing several times. You can write a function so that some bits of what it does aren't completely specified, and when the function is used the details get filled in. This is like having a recipe that will make several different kinds of pie, we suppose. Functions are also useful even if you're only going to use each function once. They don't make your program any shorter then, but they do make it easier to understand. *You'll probably just have to take our word for this, until you've written lots of programs and discovered it for yourself!* Defining and using functions ---------------------------- To define a simple function that does the same thing every time you use it, do something like this: .. sourcecode:: python def some_name_or_other(): do something do something else blah blah blah And to use it, you just say .. sourcecode:: python some_name_or_other() That will do basically the same as copying everything inside the function definition would have done. Local variables --------------- Suppose you say .. sourcecode:: python def say_boo_twice(): boo = 'Boo!' print(boo, boo) boo = 'boo hoo' say_boo_twice() Then after doing that, ``boo`` will still be a name for the string ``'boo hoo'`` -- *not* for ``'Boo!'``. So this is something that's different from what would happen if you just copied the definition of the function instead of calling the function by its name. There's a good reason for this. It means that functions can't have terribly unexpected effects. Someone reading the second half of that little program wouldn't have any reason to suspect that ``say_boo_twice()`` would change the value of ``boo``. So, making changes to variables **local** to the function makes programs easier to understand: you don't need to know all about what's inside ``say_boo_twice()`` in order to understand a piece of program that uses it. The variable ``boo`` inside ``say_boo_twice`` is called a **local variable**. Global variables ---------------- Actually, we lied to you when we said that calling a function can't have unexpected effects on variables' values. It can, but you have to ask for this to happen. If we change the program above by adding one extra line .. sourcecode:: python def say_boo_twice(): global boo # This is the extra line boo = 'Boo!' print(boo, boo) boo = 'boo hoo' say_boo_twice() then the value of ``boo`` *will* change. Saying ``global boo`` means: The variable ``boo`` is not a local variable. (**Global** is the opposite of **local**.) You shouldn't need to do this very often, especially because of a useful rule: If a function uses a variable *but never changes its value*, then the variable is assumed to be global. So your functions can *use* variables from the rest of your program without the trouble of writing ``global``; it's only if you want to change those variables that you need to say they're ``global``. And, usually, you shouldn't need to do that. Functions with arguments ------------------------ The most interesting functions have arguments. An argument is a piece of information you give when using a function that makes a difference to what the function does. If you have a recipe that tells you how to make any number of pancakes (allow a pint of milk for every 12 pancakes , etc) then the number of pancakes is an **argument** to the recipe (though cookery books don't usually put it that way!). Here's how you define a function with arguments. .. sourcecode:: python def print_two_things(x, y): print('x is', x) print('y is', y) ``x`` and ``y`` are called **parameters**. You can probably guess that if you say ``print_two_things(1, 'boing!')`` then the computer will say:: x is 1 y is boing! The arguments to a function are really just a special kind of local variable: inside ``print_two_things``, ``x`` and ``y`` (the *parameters*) are local variables whose values are given when you say ``print_two_things(1, 'boing!')`` or whatever. It is as if we had the statements: .. sourcecode:: python x = 1 y = 'boing!' inside the body of the function definition. The difference is that you can decide what values the parameters will have each time you call the function. Returning values ---------------- Some functions don't just *do* things; they also produce results. For instance, you can write a function that takes two arguments and has, as its result, the sum of those two arguments. (There's no particular reason why you'd want to do that; it just makes a simple example.) Here's how you do that. .. sourcecode:: python def add(a,b): return a + b The magic word ``return`` means that what follows is sent back from the function to the part of the program that **called** it. So, you could use this function like so: .. sourcecode:: python print('3 plus 4 is', add(3, 4)) which would, unsurprisingly, print ``3 plus 4 is 7``. Optional arguments ------------------ Sometimes the arguments to a function are *usually* the same, but occasionally you want to do something different. You can save some typing by using optional arguments . Here's how to do that. .. sourcecode:: python def do_something(x, y=999): print(x, y) You can now use this in three ways. * As an ordinary function with two arguments. ``do_something(5, 6)`` does just the same as if the definition had just begun with ``def do_something(x, y):``\ . * As a function with *one* argument. If you don't say what value ``y`` should get, it will be set to 999 for the duration of the function. So, ``do_something(1)`` is the same as ``do_something(1, 999)`` . * As a function with one argument, and a keyword argument which you can call by name. In other words, you can say ``do_something(8, y=123)``\ . Obviously this isn't very useful, but if ``do_something`` had had *several* optional arguments this lets you give special values to some of them but not others. Weird stuff ----------- There are some slightly strange things you can do with functions. For instance, as far as Python is concerned, a function is just another object, no more unusual than a number or a string. So you can use one function as an argument to another. For instance, the built-in function (i.e., a function Python provides for you without you having to define it) called ``map`` works like this: .. sourcecode:: python >>> def thrice(x): ... return 3 * x ... # Just hit Enter here. >>> list(map(thrice, [1, 2, 3, 100])) [3, 6, 9, 300] You might find a use for this some day. Why bother? ----------- It's possible to write quite complicated programs without bothering with functions at all. What does using functions gain you? * *Your programs will be clearer*. It's easier to understand a program when it's divided up into manageable portions, and functions are a useful way of doing that. * *You won't have to think so hard*. If your program is divided up sensibly into functions, you can understand what each bit of it does without having to remember the details of every other bit. When you see ``update_high_scores()`` you'll know what that does, without the effort of reading through the code that actually updates the high scores, so it will be quicker to understand the bit of the program that uses ``update_high_scores()``\ . * *You'll save typing*. If you have to do the same thing (or even roughly the same thing) several times, put it in a function. Then you only have to explain how to do it once. * *Your programs will be more adaptable*. If you find that you need to change something about your program, it's much easier to do that if it's neatly packaged up into functions. Otherwise you'll have nightmares wondering whether you really caught *every* place in the program that deals with the player's score and adjusted it for the new scoring rules. * *You'll be able to re-use more of what you write*. With a bit of luck, you'll find that some functions you write are useful for several things, so that you can use the same function (or a slight variant) in several programs. That saves you the effort of having to write it several times! You probably won't see the point of lots of the things on this list until you've actually written (or read!) some complicated programs. But once you've done that, you'll discover that functions are essential for keeping large programs under control.