An Introduction To Python
An Introduction To Python
Table of Contents
Python is a little different from other languages like C/C++ and Java, in that functions are not
magic constructs, but values. Yes, functions in Python, are like integers in C. They are simply
values and can be passed to other functions/object constructors, and so forth. We've already seen
a pretty simple example of a Python function in the form of the venerable "Hello World!"
program. Let's take another look at it:
# hello.py
def hello():
print "Hello World!"
return
In the above code there is really only one new keyword: def. def is the keyword used when
defining functions. Arguments are passed in paranthesis just like C, and the return statement
can't return multiple values. However, since lists, tuples, and dictionaries are basic types they
can be returned instead. I'll illustrate this later. A quick thing to note about Python functions:
They always return a value. However, if no return value is specified, or you don't use the return
keyword, Python automatically returns the value None.
Now let's play around around a bit with the idea of functions as objects, and then will show some
some more advanced functions.
Let's write a simple function called "map", which maps a function across a list, applying that
function to each list element. I'm also going to illustrate recursion by writing a recursive and
non-recursive version of "map".
# map.py
# We can use append here
def map( fun, list ):
nlist = []
for item in list:
nlist.append( fun( item ) )
return nlist
# But here we have to use concatenation, or the + operator for lists.
def rmap ( fun, list ):
if list == []:
return []
else:
return [fun( list[0] )] + rmap( fun, list[1:] )
Now notice how a function, in this case increment is passed to map and rmap, just as if it were a
number or some other data. Why is that? Because functions are data in Python, not just special
labels for code blocks(or whatever they are in C/C++). There is also a nice example of the
difference between recursive and non-recursive code in Python. I find the first form more
intuitive, but the second form is more interesting.
Pretty tame so far. Aside from the fact that functions are first-class values in Python, they don't
seem to exciting. So let's try showing off a few more features of Python functions.
Let's assume that I have a C++ code in which I want to return 3 values. There are a number of
ways I could return
-1,0,1
from C++.
Possible Method I:
Now I am not saying that these are the only ways to return multiple values in C++, but they are a
few possibilities. However, in Python, "Possible Method I" would not work. Python passes all
arguments using "pass by reference". However, numerical values and Strings are all immutable.
You cannot change the value of a passed in immutable and see that value change in the caller.
Dictionaries and Lists on the other hand are mutable, and changes made to them by a called
function will be preserved when the function returns. This behavior is confusing and can lead to
common mistakes where lists are accidentally modified when they shouldn't be. However, there
are many reasons for this behavior, such as saving memory when dealing with large sets.
Most often when you have to return multiple arguments you will probably just use something
simple like this example. Here we just take advantage of the fact that Python includes built in
Tuples, Lists, and Dictionaries, and return one of these objects to encapsulate the multiple
values.
# multiple-returns.py
a, b, c = 0, 0, 0
def getabc():
a = "Hello"
b = "World"
c = "!"
return a,b,c #defines a tuple on the fly
def gettuple():
a,b,c = 1,2,3 # Notice the similarities between this and getabc?
return (a,b,c)
def getlist():
a,b,c = (3,4),(4,5),(5,6)
return [a,b,c]
Sometimes, when dealing with lists and dictionaries it is actually more efficient or effective to nt
take advantage of the fact that these more complex objects are passed-by-reference. Take a look
at the following example:
Finally it is important to be aware of possible bugs that can occur with references to Lists and
Dictionaries. Consider the following code intended to...( I need to dig up an example of one of
these pass-by-reference gotchas.)
Python allows you to mess around with arguments a little more then C/C++. Let's see a few
examples of how functions can be defined and how they can be used.
# Simplest Arguments
def multiprint( n, txt ):
i = 0
while i < n:
print txt
# Default Values
def multiprint( n=5, txt="" ):
i = 0
while i < n:
print txt
# Labels
def multiprint( n=5, txt="" ):
i = 0
while i < n:
print txt
# Now, let's say I want to just define fun and base, and not list.
# I could do this:
fold_right( fun = lambda x y: x + y, base = 0) #Look 'ma, no list!
# This makes sense if you have a large argument list (5, 10, +
variables),
# some default and some required. You can easily specify just the
# variables necessary to run the function and leave the defaults alone.
Default arguments are nice, allowing you to simply define values to be used if none are
specified. This makes long argument lists a lot nicer to work with. On the other hand, having
default arguments, especially with complicated functions, you'll often end up with a mix of
default and required variables. However as soon as your function requires a variable it requires
you to either re-order your argument list, or specify a bunch of arguments with default
values(whether you want to set those defaults or not). Python supplies you with an easy way to
set just the arguments necessary and none that aren't. Simply specify the name of the variable in
the call to the function. These "labels" can be used in any python function and they can help in
dealing with complicated functions and arglists.
Lambda Expressions (Anonymous Functions)
As if the last section wasn't cool enough, let's try "lambda expressions", a concept borrowed
from Lisp and other functional languages. Lambda expressions return functions as results. They
build functions without assigning names to them. A normal function declaration assigns the
functions value to the name of the function, but lambda expressions do not.
Why would you want this dubious functionality? Because lambda expressions are nice to use in
places that a function declaration wouldn't normally be allowed, and to write quick and dirty
functions on the fly. Sometimes you want to build functions(callback handlers in gui's, object
member data accessors, and so on), and using lambda expressions makes that a lot easier.
So lambda lets you define and use a function inside an if statement body, or inside a list.
However, lambda expressions are just that, expressions. It is difficult to write a complicated
function because statements are not allowed.
# lamba-map.py
# Remember our "map" function from a little earlier?
import map
list = xrange(0,2,100)
Links to code...
Table of Contents