Learn about collections of variables: data structures
Learn about objects
Learn about methods which allow you to do things to objects
Now that we know about variables, it would be handy to group them together in some way. In Python there are many ways to do this: lists, tuples, dictionaries, and sets, among others. These group arbitrary variables and/or values together, (e.g., strings and integers and floats) in containers.
We'll go through some of the various data structures, starting with lists.
Lists are denoted with [ ] and can contain any arbitrary set of elements, including other lists!
Elements in the list are referenced by an index number (index). Similar to the strings we encountered in the last lecture, the indices begin at 0. Remember that this is different from what you may be used to, which would be that the first element is index 1; in Python, the first element is index 0.
You can count from the end to the beginning by starting with -1 (the last item in the list), -2 (second to last), etc.
Lists have methods that allow items to be sorted, deleted, inserted, sliced, counted, concatenated, replaced, added on to, etc.
Let's take a look at some examples:
mylist=['a',2.0,'400','spam',42,[24,2]] # defines a list
print (mylist) # prints the list
['a', 2.0, '400', 'spam', 42, [24, 2]]
But if we want to print out the third element in list we use index number 2:
print (mylist[2]) # print the third element in the list (starting from zero)
400
And similarly, to print the fourth element we use index number -1:
print (mylist[-1]) # print the last element
[24, 2]
But if you want to print, say, the last three elements, you can't do this:
print (mylist[-3:-1])
['spam', 42]
This is because the slice list[begin:end] means from index = begin up to and not including index=end. To actually slice out the last three elements, you can do it this way:
print (mylist[-3:])
['spam', 42, [24, 2]]
Unlike strings, you can change list elements "in place". By "in place" we mean that you don't have to assign it to a new variable name; the list gets change "in place":
mylist[1]=26.3 # replaces the second element
print (mylist)
['a', 26.3, '400', 'spam', 42, [24, 2]]
To delete, for example, the 4th element from a list, you can use the command del:
del mylist[3] # deletes the fourth element
mylist
['a', 26.3, '400', 42, [24, 2]]
Like strings, you can slice out a chunk of the middle of a list and assign it to another variable:
newlist=mylist[1:3] # takes the 2nd and third values and puts in newlist
#note it takes out up to but not including the last item number
print (newlist)
[26.3, '400']
Making copies of lists behaves in ways you might not expect if you are coming from other programming languages. We will learn more about copies of lists in later lectures, but here are some pro tips for now.
You can assign a list to another variable name like this:
mycopy=mylist
mycopy is now a copy of mylist. But it is inextricably bound to the original, so if I change one, I change the other. This type of copy is known as a shallow copy.
mylist[2]='new'
print (mylist)
print (mycopy)
['a', 26.3, 'new', 42, [24, 2]] ['a', 26.3, 'new', 42, [24, 2]]
See how mycopy was changed when we changed mylist?
To spawn a list that is an independent object (a deep copy), you can do this:
mycopy=mylist[:]
# now try changing mylist...
mylist[2]=1003
print (mycopy) # if there are two things to print, use 'print'
mylist # otherwise only prints the last one
['a', 26.3, 'new', 42, [24, 2]]
['a', 26.3, 1003, 42, [24, 2]]
See how mycopy stayed the way it was, even as mylist changed?
There are more ways to make shallow and deep copies of Python objects which we will explore further in Lecture 10.
An object in Python is a collection that has attributes and methods. The list variable mylist is an example of an object - a list object. In fact they are classes which we will learn more about in later lectures, but I just wanted to mention them here.
So what is so special about objects? Python objects have methods which allow you to do things to the object. Methods have the form:
object.method( )
or
object.method(argument1, argument2,...)
Here, argument1 is something that can get passed into the method.
Let's look at a few examples starting with the .append( ) method for lists (which appends something (the argument) to the end of a list).
mylist.append('why not?')
# append() is a method of lists that appends the argument 'why not?' to the list
print (mylist)
['a', 26.3, 1003, 42, [24, 2], 'why not?']
.count( ) is another method. Let's see what it does:
mylist.append('why not?')
print (mylist.count('why not?') )
2
The method .count( ) returns the number of times the argument occurs in the list. [NB: the argument is the stuff inside the parentheses of the method - in this case 'why not?'.]
Another very handy list method is the .index( ) method. It returns the index of the desired argument in the list. For example, if we wanted to know what the index of the element, 42, is in mylist, we would type:
print (mylist.index(42) )
3
These are just a few of the methods for lists. To view all of the methods for a list object, see: https://docs.python.org/tutorial/datastructures.html
For example, we could make this list:
santas_list=['naughty','nice']
print (santas_list)
# and check it twice
print (santas_list)
['naughty', 'nice'] ['naughty', 'nice']
Earlier, we made a list by defining a variable with square brackets. We added to that list with append( ). Another way to generate a list is to use range( ), which is one of the python built-in functions we mentioned in Lecture 2. The function range( ) is a list generator and can be used to generate a list of integers between two numbers, the start and end, where each number is separated by a specified interval. You can make a lisa from the generator like so: list(range(start,end,interval)). Note that range, like list slicing, goes up to but does not include end.
# creates a list from 2 to 20 (not including 20!) at intervals of 4
numlist=list(range(2,20,4))
print (numlist)
[2, 6, 10, 14, 18]
Tuples are another important object in Python that are similar to lists, but have important differences. They are denoted by parentheses ( ) and consist of values separated by commas.
Like lists, they can contain different elements, but unlike lists, the elements cannot be changed in place. Their primary use is to pass information into and out of programs as we shall see in the coming lectures.
Similar to both lists and strings, you can slice, concatenate, etc. For more see:
http://docs.python.org/tutorial/datastructures.html#tuples-and-sequences
Here is one way to generate a tuple:
t = 1234, 2.0, 'hello'
print (t)
(1234, 2.0, 'hello')
Or, the other way around:
a,b,c=t
print (a)
print (b)
print (c)
1234 2.0 hello
You can access an element in a tuple by using the index number, exactly like a list.
t[0]
1234
But, you can't change it:
t[0]='haha'
print (t)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-18-f007a382b75c> in <module> ----> 1 t[0]='haha' 2 print (t) TypeError: 'tuple' object does not support item assignment
There are more data structures that comes in handy and one is the set. They are denoted with curly braces { }. A set "contains an unordered collection of unique and immutable objects."
You can create sets in several ways. The first would be the use the python built-in set( ) function on a list:
S1=set(['spam','ocelot',42])
S1
{42, 'ocelot', 'spam'}
Notice how the order changed.
Also, notice what happens if we violate the "unique" part of the definition:
S2=set(['spam','ocelot','ocelot'])
S2
{'ocelot', 'spam'}
Only one of the ocelots made it into the set. [By the way, "ocelot" is another Monty Python joke - look it up if you like.]
Sets contain immutable objects, but they themselves can be changed. For a more complete list of methods see:
https://www.python-course.eu/python3_sets_frozensets.php
But here are a few:
# add
print (S1)
S1.add('chocolate')
print (S1)
{'ocelot', 42, 'spam'} {'ocelot', 42, 'chocolate', 'spam'}
# clear
S2.clear()
S2
set()
See how S2 is now just an empty set object set( ).
Now let's try copying S1.
# copy
S2=S1.copy()
print (S2)
S1.clear()
print (S1)
print (S2)
{'ocelot', 42, 'chocolate', 'spam'} set() {'ocelot', 42, 'chocolate', 'spam'}
the .copy( ) method for sets does not work like copying lists - it made an independent object S2 which did not clear when S1 got cleared.
.difference is another handy method - it can be used to find what is different about two sets.
# difference
S1=set(['spam','ocelot',42])
S2=set(['spam','ocelot'])
S1.difference(S2)
{42}
But - you say - you want to know what is the same in two sets. For that, use the .intersection method.
# intersection
S1.intersection(S2)
{'ocelot', 'spam'}
There is a nice short cut for this:
S1&S2
{'ocelot', 'spam'}
Finally, you can define a set just using curly braces:
S3={42,'spamalot','Ni'}
S3
{42, 'Ni', 'spamalot'}
'Ni' is another joke from Monty Python and the Holy Grail where there were some characters calling themselves the "Knights who say Ni!". "42" is not from Monty Python, but from the Hitch Hikers Guide to the Galaxy - but people who like Monty Python also like the Hitch Hiker's Guide. By the way, "42" is the answer to "What is the meaning of life, the universe, and everything?". Now you know.
Your notebook must have the correct name, be fully commented and run as expected to receive full credit.