Computer Science Canada [Python-tut] Functions: arguments, objects, decorators |
Author: | wtd [ Wed Apr 06, 2005 5:04 pm ] | ||||||||||||||||||||||||||||||||
Post subject: | [Python-tut] Functions: arguments, objects, decorators | ||||||||||||||||||||||||||||||||
Understanding functions is critical to understanding Python. To introduce a function definition, we use the "def" keyword. Let's look at a simple function.
This is about as straightforward as it gets. Now, let's greet a person. For this, we'll need to get the name of the person as an argument.
Again, this is quite straightforward. We can take more than one argument.
But, what happens now if the person being greeted doesn't have a last name (or is ahamed to make it known, lest his family's longstanding feud with the McCoy clan come back to haunt him)? In that case, we'll have simply printed an extra space after the first name for nothing. We can use a conditional to catch this.
But, in this case, why bother even supplying the empty string as an argument? Well, we've little choice. Python doesn't allow us to overload functions by argument count. However, we can make arguments optional by providing default values.
Now, here's a question: what if I forget which argument comes first? Well, in that case I can use named arguments.
But, going back to single names, what if I want to greet lots of people? Well, in this case we need to slurp up all of the arguments that aren't otherwise accounted for into a list.
Earlier I demonstrated that named arguments can be used when a function is called. Well, what if I provide names that aren't arguments? I can collect those as well, and then deal with them in my function. In this case, let's use that to collect names, and aliases.
Now, for the fun stuff. Functions in Python are objects. What does this mean, you say? Well, it means that we can pass them around like any other value. The value of this is especially easily seen with functions like filter, which uses the output of a function supplied to it to determine if it should discard a value or not from a list. First we create a list of numbers from 0 to 9 with the range function. Then we create a function which determines if a number is odd. Then we create another list based on filtering the original list.
What other interesting things can we do with functions as objects? Well, we can create local functions.
Since "add(4)" returned a function, "a" is simply a function which adds 4 to any argument it's given. There's only one problem. The name of the "a" function is still "temp," since that's what it started out as. Fortunately we can fix that up.
Now, let's use something like this to comes up with another example of filter in action.
Starting with Python 2.4, an interesting feature was added called "decorators." But first, let's look at the way the same things were accmplished before.
This looks pretty bizarre, but it's easier to understand when you go through it step by step. At the top is a function called "print_before" which takes an argument to print. This is the only function involved whose name we really care about. That function defines another function called "temp" which takes a function as an argument. Inside that we define yet another function called "execute_func" which takes a list of arguments. Inside that function we print "a" that was supplied to "print_before" and call the function it was supplied with using the arguments provided to execute_func, returning the output. The "temp" function then changes the name of execute_func to match the function passed in, and returns execute_func. The "print_before" function then returns "temp." Now, let's look at using this to "wrap" another function.
But that's pretty messy, so Python's designers decided to make it nicer to look at.
Now, that's not a terribly useful example, but hopefully demonstrates the power of decorators. Let's look at a more useful example.
Questions? Comments? |