3. Basic data types

3.1. Lists

Lists are collection of objects on Python:

In [1]:
somelist = ["Now", "my", 293, 43.2]
somelist[0]
somelist[2]
Out[1]:
293

Note that the types of the object inside the list do not need to be the same. The first thing R users shall notice is that we index the elements starting from 0 (instead of 1), there’s a Computer Science explanation for this that is beyond the scope of this text.

Now consider the following code:

In [2]:
somelist = ["Now", "my", 293, 43.2]
somelist.append("something else")
somelist[4]
Out[2]:
'something else'

For many this syntax might sound a little different, here we actually have a function of somelist that modified the object for us (see footnote 1). We will call those functions methods whenever they have such syntax (object.method()).

Now take a look at this example:

In [3]:
list1 = ["Now", "my", 293, 43.2]
list2 = [43, "Well"]
list1.extend(list2)
list1
Out[3]:
['Now', 'my', 293, 43.2, 43, 'Well']

3.1.1. Exercise

Using IPython, type list1. then press tab to see a list of suggested methods, choose one of them and place a “?" before the code to check the method documentation.

Example:

  1. Type list1.
  2. Press tab.
  3. Select list1.pop.
  4. Place a ? before it, therefore obtaining ?list1.pop.
  5. Press ENTER, read the documentation and press q to quit.
  6. Try to use it (e.g.: list1.pop() or list1.pop(0)).

Note that you can also use []. instead of list1. or the name of another variable before pressing tab.

3.2. Tuples

Tuples are similar to lists in the sense that they are a collection objects on Python:

In [4]:
somelist = ("Now", "my", 293, 43.2)
somelist[0]
somelist[2]
Out[4]:
293

However, they are immutable (that is, they cannot be modified), and therefore, this will give you an error message:

somelist = ("Now", "my", 293, 43.2)
somelist[0] = "Later"

Of that kind:

TypeError: 'tuple' object does not support item assignment

Note that this is not a tuple:

In [5]:
("Now")
Out[5]:
'Now'

It’s just a plain string (check it with type(("Now"))). If you want to create a single element tuple, you have to use this instead:

In [6]:
("Now",)
Out[6]:
('Now',)

3.3. Dictionaries

Dictionaries are similar to lists in the sense that they “store" multiples objects:

In [7]:
{"apple": 12, "banana": 24, "lemon": "unknown"}
Out[7]:
{'apple': 12, 'banana': 24, 'lemon': 'unknown'}

However, as you can see, the elements are accessed by a string index:

In [8]:
somedict = {"apple": 12, "banana": 24, "lemon": "unknown"}
somedict["apple"] = somedict["banana"] + 23
somedict["apple"]
Out[8]:
47

Well, in fact the key does not need to be a string, it can actually be other things too (see footnote 2):

In [9]:
somedict = {"apple": 12, 324: "something", (34, 332): "crazy"}

And (somewhat contrary to lists), you can add elements to your dictionary without much trouble (like having to use the list append method).

In [10]:
somedict = {"apple": 12, "banana": 24}
somedict["orange"] = 83.5
somedict
Out[10]:
{'apple': 12, 'banana': 24, 'orange': 83.5}

Replace also works well, of course:

In [11]:
somedict = {"apple": 12, "banana": 24, "orange": 83.5}
somedict["orange"] -= 10 #lost 10 oranges on my way home
somedict["apple"] = 0 #eat them all
somedict
Out[11]:
{'apple': 0, 'banana': 24, 'orange': 73.5}

Or easilly delete elements too, using del:

In [12]:
somedict = {"apple": 12, "banana": 24, "melon": 42}
del somedict["melon"]
somedict
Out[12]:
{'apple': 12, 'banana': 24}

You can also create a dictionary using the function dict:

In [13]:
dict(apple=12, banana=24, lemon="unknown")
Out[13]:
{'apple': 12, 'banana': 24, 'lemon': 'unknown'}

Note that the arguments of the function dict have names, so you have your first example of named arguments for functions (we’ll see more about this later).

3.3.1. An optional lookahead

Take a look at OrderedDict, which works in similar fashion to dict, but remembers the insertion order (e.g.: when its "converted" to a list):

In [14]:
from collections import OrderedDict
somevar = OrderedDict(a=23, b=32)
somevar["something"] = 643
list(somevar)
Out[14]:
['a', 'b', 'something']

3.4. Sets

Sets in Python are really what your intuition might tell from the notion of sets you (might) have from Mathematics:

In [15]:
someset = {243, 54}
someotherset = {243, 54, "ke", 2.3}

You can also create a set from a list or a tuple:

In [16]:
someset = set([243, 54])

Note that sets elements are unique:

In [17]:
someset = set(["aa", 243, 54, 243, 1, "aa"])
someset
list(someset)
Out[17]:
['aa', 243, 54, 1]

Will give you:

In [18]:
{54, 1, 243, 'aa'}
[54, 1, 243, 'aa']
Out[18]:
[54, 1, 243, 'aa']

Now let’s do some Mathematical operations with sets:

In [19]:
set1 = set(["aa", 243, 54.3, 243, 1])
set2 = set(["aa", 4.3, 1, "aa"])
set2.add(54.3) #adds element to set
set1.discard("aa") #removes element from set
set3 = set1.intersection(set1, set2)
set3
Out[19]:
{1, 54.3}

Which gives us:

In [20]:
{1, 54.3}
Out[20]:
{1, 54.3}

Note try using methods union, difference and symmetric_difference. Python also has the function frozenset, which is to set, as tuple is to list. That is, is has the same properties of set, except that it is immutable and therefore:

somefset = frozenset(["aa", 243, 54, 243, 1, "aa"])
somefset.add(432)

will give you an error message:

AttributeError: 'frozenset' object has no attribute 'add'

Time will come for we to discuss the usage of mutable function like tuple and frozenset.

3.5. Important subsection

OK, no clickbait here, this one is really important, consider the following code:

In [21]:
somelist = ["now", "you should try", 70]
someotherlist = somelist
somelist.append("to do something else")
somelist[0] = "later"
someotherlist
Out[21]:
['later', 'you should try', 70, 'to do something else']

Which will output:

In [22]:
['later', 'you should try', 70, 'to do something else']
Out[22]:
['later', 'you should try', 70, 'to do something else']

Well, that might have been a little unexpected, specially for those that came from an R perspective. We made a copy of somelist to someotherlist?, didn’t we? So why did our later change on somelist affected someotherlist? Well, it turns out that, we did not copy it of somelist at all (see footnote 3).

To understand why, first remember that everything in Python is an object, so let’s use the function id to give us the unique identifier of each object:

In [23]:
somelist = ["Now", "my", 293, 43.2]
someotherlist = ["Now", "my", 293, 43.2]
somelistagain = somelist
id(somelist)
id(someotherlist)
id(somelistagain)
Out[23]:
139846486935176

As you’ll see, somelistagain references the same object as somelist. Now just try this out:

In [24]:
somelist = ["Now", "my", 293, 43.2]
someotherlist = somelist.copy()
somelist.append("something else")
someotherlist
Out[24]:
['Now', 'my', 293, 43.2]

And also this:

In [25]:
somelist = ["Now", "my", 293, 43.2]
someotherlist = list(somelist)
somelist.append("something else")
someotherlist
Out[25]:
['Now', 'my', 293, 43.2]

Try checking the id of somelist and someotherlist on the examples above.

3.6. Footnotes

  1. R users might have expected something like: somelist = append(somelist, "something else") which is not valid Python code.
  2. But not anything, it has to be hashable object, which is beyond the scope of this work. Try using a list as a key for example: {"something": 43, [3,2]: 32}, it won’t work!
  3. Tip for C/C++ programmers: think of Python variables as pointers to objects.