Functions are defined with the keyword 'def' following the function name and a list of formal parameters. You can also have a string literal as the first line of the function and Python takes it as the function's documentation string (docstring) which is a pretty neat feature.
One of the first things to look at is how parameters are passed. The tutorial I read doesn't explain it very well (it made it seem like pass-by-reference). I played around with it myself and it looks like it passes by value, but with objects it passes a reference by value. Much like Java, where objects are basically passed by reference and primitive objects are passed by value.
When you define a function, the body of code is created and then the definition name specified is bound to that body of code. The def name is then inserted into the current symbol table. Since the def name is just a reference to the body of code, you can easily create multiple aliases of functions by assigning other names to the initial name. It's kind of like working with function pointers in C, but you don't really have to deal with pointers.
Note that you can create nested functions since it simply binds a name to the code and inserts it into the current symbol table. Scoping applies here as it would with any variable.
With all of these features, it's very easy to create complex functions. I remember in ML when you could create functions that return functions, though I forget what this is called. It's very easy to do the same thing in Python, and though I forget why it's useful, I remember thinking, "wow, this makes this problem really easy to solve!"
>>> def func(a):
return a + b
>>> f = func(1)
It's the use of aliasing that makes this really powerful. You can have a function that defines another function according to certain parameters, which opens up some possibilities to self modifying code and such.
Variable number of arguments
You can define a function with variable number of arguments. The easiest way of doing this is specifying defaults for parameters. It's done exactly as in C, you simply specify a value when listing the formal parameters.
The tutorial that I read about default arguments mentioned something very important about them. They are only evaluated once, which means mutable objects such as lists are shared between subsequent calls. I'm not sure if it's the same in C/C++; I'm pretty sure default arguments are evaluated each time the function is called as it probably creates several different copies of the same function and evaluates the defaults within these polymorphic copies.
This is probably best explained with an example. This is from this tutorial:
def f(a, L=):
This will print
1, 2, 3
Python also lets you specify which default arguments you want to declare. This is called "keyword arguments" and is specified by the form keyword=value in the actual parameter list. This is a great feature over C/C++ which forces you define default parameters in the order that they are listed in the formal parameter list.
Python has 2 ways of defining a function that really takes a variable number of arguments. It's similar to the elipse in C/C++ ("..."), but of course is easier to work with. The first way is to simply put an asterisk as a prefix to the formal parameter. This parameter becomes a tuple of the passed arguments (I need to figure out the difference between a tuple and a list in Python).
The second way is to put 2 asterisks before the formal parameter. This is a really interesting technique. This parameter becomes a dictionary, and you can pass arguments in the form of key=value in the actual parameter list.
Of course, this is best explained by example:
>>> def func(*a):
('a', 'b', 3)
>>> def func(**a):
keys = a.keys()
for kw in keys: print kw, ':', a[kw]
a : 1
b : 2
Any number of formal parameters can occur before these variable arguments. These two techniques can also be combined in one function, but the *a must come before **a. I also that it was interesting that you have to sort the dictionary because the order of those parameters is undefined. I tried it without sorting and it seemed to always be in the order that I passed, but I guess the documentation doesn't lie.
Another useful feature is that instead of packing actual parameters into one formal parameter as a tuple, you can actually unpack an actual parameter into multiple formal parameters. You do this with the asterisk.
>>> def func(a,b);
return a + b
>>> args = [1,2]
I'm finding more and more similarities between Python and a functional language such as ML. You can actually specify anonymous fuction in Python! You do this with the lambda keyword, and my previous example of a function returning a function could be written in a prettier form:
>>> def func(a):
return lambda b: a + b
>>> f = func(1)
An anonymous function is basically a body of code without any definitions bound to it. I think my professor said that they are unofficially called "thunks"... or officially? Anyway, they are very helpful.
That's it for functions. Sheesh, I haven't even gotten to classes yet. I really need to hurry up on this thing.