include "../_i/1.h"; ?>
Similar to lists, but immutable.
>>> t = ('a', 'b', 'c') >>> for elem in t: ... print elem a b c >>> print t[1] b >>> t.sort() ... AttributeError: 'tuple' object has no attribute 'sort'
Despite the surface similarities, tuples have a very different purpose from lists.
A list
is for a variable-size collection of
similar things.
A tuple
is generally for describing multiple
aspects of a single thing, where each spot in the tuple has
an (implicit) meaning. For instance, a tuple about me: ('Carl',
'Meyer', 29, 74, 165)
.
But if we've got a group of people, use a list (of tuples!):
[('Carl', 'Meyer', 29, 74, 165), ('Fred', 'Flintstone', 43, 65, 257)]
Tuples are fine for simple data structures, where you can easily keep in your head what field means what. Later we'll cover classes, a more explicit way to define compound data structures.
Last week we saw simple string concatenation: print 'Your name is ' + first_name + ' ' + last_name
. This breaks if we try to concatenate something that isn't a string:
>>> age = 29 >>> print 'You are ' + age + ' years old. ... TypeError: cannot concatenate 'str' and 'int' objects
In most cases, you're better off with string formatting:
people = [('Carl', 'Meyer', 29, 74, 165), ('Fred', 'Flintstone', 43, 65, 257)] for person in people: fn, ln, age, height, weight = person print '%s %s is %s years old, %s inches tall, and weighs %s.' % (fn, ln, age, height, weight)
people = [('Carl', 'Meyer', 29, 74, 165), ('Fred', 'Flintstone', 43, 65, 257)] for person in people: print '%s %s is %s years old, %s inches tall, and weighs %s.' % person
Say we're working with file paths, so we have a variable path = '/Volumes/HOMES/Classes/COMM385'
. We want to know what the last bit of that path is. So we split the string:
>>> bits = path.split('/') >>> bits ['', 'Volumes', 'HOMES', 'Classes', 'COMM385'] >>> bits[-1] 'COMM385'
Now we'll change the last bit of the path, and then put it back together into a single string:
>>> bits[-1] = 'CS101' >>> bits ['', 'Volumes', 'HOMES', 'Classes', 'CS101'] >>> '/'.join(bits) '/Volumes/HOMES/Classes/CS101'
Functions can have multiple arguments (of course), and some of them can be optional:
def first(a_list, num=1): """ Return the first X elements in a list (one element by default). """ return a_list[:num]So we can call this function with either one or two arguments:
>>> my_list = [0, 1, 2, 3] >>> first(my_list) [0] >>> first(my_list, 3) [0, 1, 2]
If a function has multiple optional arguments, we can specify exactly which ones we want to override when we call it:
def html_tag(contents, tag='p', attributes=None): "Create an HTML tag with contents." if attributes is None: attrs_string = '' else: attrs_string = ' '.join(['%s="%s"' % (k,v) for k,v in attributes.items()]) return "<%s%s>%s</%s>" % (tag, attrs_string, contents, tag) >>> html_tag('Some stuff', attributes={'id': 'stuff'}) '<p id="stuff">Some stuff</p>'
We can allow a function to take an arbitrary number of "keyword arguments":
def html_tag(contents, tag='p', **attributes): "Create an HTML tag with contents." print attributes if not attributes: attrs_string = '' else: attrs_string = ' '.join(['%s="%s"' % (k,v) for k,v in attributes.items()]) return "<%s%s>%s</%s>" % (tag, attrs_string, contents, tag) >>> html_tag('Some stuff', tag='div', id='stuff', class='aside') {'id': 'stuff', 'class': 'aside'} '<div id="stuff" class="aside">Some stuff</div>'
With a single asterisk, your function can collect an arbitrary number of non-keyword arguments:
def sum(*args): "Return sum of all arguments." total = 0 for arg in args: total += arg return total >>> sum(1, 2, 3) 6 >>> sum(2, 4, 6, 8, 10) 30
And, of course, you can have both *args and **kwargs in the same function:
def print_args(*args, **kwargs): "Print out all arguments." print args print kwargs >>> print_args(1, 2, 3, foo="bar", baz="quux") [1, 2, 3] {'foo': 'bar', 'baz': 'quux'}
In Python, functions are first-class values. That means we can refer to them, pass them around, assign them to variables, just like we can with numbers, strings, etc. We can even write functions that take other functions as arguments:
def apply_twice(func, argument): """ Applies a function to one argument, and then applies the same function again to the result. """ return func(func(argument)) >>> def double(x): return x*2 ... >>> double(3) 6 >>> apply_twice(double, 5)
I left out the result of that last function call - what will it be?
Chapter 4 in Dive Into Python
css_generator
that takes as
arguments a selector (i.e. ".wildtype"
) and then an
arbitrary number of attribute-value pairs (hint:
use **kwargs
), and returns a string that is a valid CSS
block. (If returning a large multi-line string, it's often handy to
build it up as a list of strings, each element one line, and then at
the end return "\n".join(list_of_lines)
.) For instance,
if I call css_generator(".wildtype", color="#66CC00")
,
the return value should be '.wildtype {\ncolor:
#66CC00;\n}'
map
that takes two arguments: a
function of one argument, and a list. Return the result of applying
the given function to every element of the list. For instance, if I
have def double(x): return 2*x
and I
call map(double, [2, 4, 3])
, the result should
be [4, 8, 6]
.For each of these functions, demonstrate that they work by writing
test code that uses them. Use the if __name__ ==
'__main__':
trick discussed in Dive Into Python
section 2.6 so that your test code runs if you run python
my_file.py
, but does not run if you import your module.