Home      |       Contents       |       About

Prev: -       |       Next: Constructing lists

The 'list' object


  • A list is a sequencial structure: it contains other object items (of any type) in an ordered and indexed fashion.

List features

  • A list is a highly flexible data structure with the following main features:
    • ordered: the list items are ordered (sequenced) and they can be sorted in many ways.
In [1]:
alist = [1,2,3,4,5] 
[1, 2, 3, 4, 5]
  • indexed: list items are referenced by an integer index. Indexes are placed within square brackets next to the list name. The first index in a list is always zero
In [2]:
alist = [1,2,3,4,5] 
  • iterable: When used in a for loop a list can return its items one-by-one to the iterator variable.
In [5]:
alist = [1,2,3,4,5] 
for i in alist:
    print(i, end=' ')
1 2 3 4 5 
  • mutable: List items can be altered 'in place' (that is, in the memory places they occupy without a new copy of a list being created.
In [6]:
alist = [1,2,3,4,5] 
alist[0] = 100
[100, 2, 3, 4, 5]
  • heterogeneous: list items may be of various typs (integers, strings, floats, other Python types, user-created types, etc.)
In [8]:
alist = [1,2,3,4,5] 
alist[0] = 15.47
alist[2] = 'X'
alist[3] = True
[15.47, 2, 'X', True, 5]
  • The 'list' object is one of the most important data structures in Python. It provides the basis for building more advanced and highly efficient data structures that facilitate high level data processing and scientific computing.

List indexing and assignment

  • The len() function can be called with a list argument to return the number of list items
In [9]:
alist = [1,2,3,4,5]
  • See the pythontutor visualization of alist: The list contains pointers to item objects (integers in this example)
  • Last item index is: len(alist)-1
In [11]:
alist = [1,2,3,4,5]
alist[0], alist[3], alist[len(alist)-1] 
(1, 4, 5)
  • List items can be of various types
In [10]:
import math                          
alist = [1,2,3,4,5]
blist = [12.7, 'alpha', math.pi, 100]
x = blist[0]-alist[2]
  • List item assignment can be done applying the rules/operators that are valid for the type of the item
In [13]:
alist = [1,2,3,4,5]
blist = [12.7, 'alpha', math.pi, 100]
blist[0] = alist[0] + alist[len(alist)-1]     
[6, 'alpha', 3.141592653589793, 100]
  • Index can be negative. In this case index '-1' denotes the last element of the list
In [14]:
alist = [1,2,3,4,5]
alist[-1], alist[-5]
(5, 1)
  • List concatenation(like strings): Lists can be extended by adding new lists
In [26]:
alist = [1,2,3,4,5]
clist = alist + [10, 12]
[1, 2, 3, 4, 5, 10, 12]
  • Similarly to strings lists can be multiplied by integers
In [17]:
# Note that integer * list multiplication does NOT mean that list items are multiplied by the integer
blist = [12.7, 'alpha', math.pi, 100]
dlist = 2*blist
[12.7, 'alpha', 3.141592653589793, 100, 12.7, 'alpha', 3.141592653589793, 100]

Deleting a list / Item in a list

  • Items in a list or the entire list can be deleted with the del command
  • The syntax of del is simple:
      del object_name
  • When del is executed the binding between an object and the object_name is cancelled and the object_name is removed from namespace.
  • This command works for objects of all types
  • In the following example we first delete the first list item and then the entire list. After deleting the list its former name is reported as "not defined"
In [3]:
alist = [1,2,3,4,5]
del alist[0]

del alist
[2, 3, 4, 5]
NameError                                 Traceback (most recent call last)
<ipython-input-3-a35aa046ad3b> in <module>()
      5 del alist
----> 6 alist

NameError: name 'alist' is not defined

List is 'mutable'

(a string is not) 
  • For a data structure to be mutable means that its item objects can be changed 'in place' (meaning: in the memory places they occupy right now) without having to create a 'mutant' (a copy reflecting the change).
  • See how mutability works for lists but not for strings in the examples below
  • Mutable list: alist is a mutable object and you can change the value of an element 'in place' (no copy)
In [18]:
alist = [1,2,3,4,5]
alist[2] = 'X'
[1, 2, 'X', 4, 5]
  • if you try to do the same as above on a string (immutable object) you get a TypeError
In [19]:
s = '12345'
s[2] = 'X'
TypeError                                 Traceback (most recent call last)
<ipython-input-19-f3e2d9d6887f> in <module>()
      1 s = '12345'
      2 print(s[2])
----> 3 s[2] = 'X'
      4 print(s)

TypeError: 'str' object does not support item assignment
  • Immutable string: a string is an immutable object and you can NOT change the value of an element 'in place' (instead a new copy of the altered string is constructed)
  • The right way to change a string is to create a new one
In [21]:
s = '12345'
snew = s[0]+s[1]+'X'+s[3]+s[4]    # Not a very efficient way to do it; wait till you see list slicing

Shared object reference in mutable lists

  • Why did 'alist' change in the code below?
In [22]:
alist = [1,2,3,4,5]
blist = alist
blist[2] = 'X'
[1, 2, 'X', 4, 5]
  • As a list is mutable, when a list object is referenced by two or more names (alist & blist, in the above example) any change in the list using one reference name is also reflected when referencing the list with another name. The programmer needs to carefully handle lists when multiply referenced.
  • See the relevant pythontutor visualization to better understand this example

List as iterable in a for loop

  • As explained in the 'for' loop section, a list is iterable and can be used as an iterable object in the 'for' loop command.
  • This property allows writing more elegant pythonic code. Consider the example below:
In [30]:
zoo = ['lion','tiger','elephant']

for i in range(3):
    print(zoo[i], end=' ')


for animal in zoo:
    print(animal, end=' ')
lion tiger elephant 
lion tiger elephant 
  • Both forms of code produce the same output
  • The first form (using index i to reference items in the 'zoo' list) is typical of most programming languages.
  • The second form is purely 'pythonic': no need to use index as the list itself returns to the iterator 'animal' the values of list elementary objects. Programmatically is more efficient and syntactically simpler.
  • But what if we need the list index in the 'for' loop?

Use the 'enumerate()' function

In [31]:
zoo = ['lion','tiger','elephant']
for i, animal in enumerate(zoo):
    print(i, animal)
0 lion
1 tiger
2 elephant
  • Enumerate returns a tuple (this data type is explained in a next section) with 'index' as the first tuple element and the list object as the second.

The 'in' operator

  • The 'in' operator in sequences (like lists and strings) is used to control for 'membership', that is, examine whether an element is included in a sequence (returns 'True') or not (returns 'False).
In [23]:
L = [1,3,5] 
print(2 in L)
In [24]:
s = 'spam'
print('s' in s)
In [25]:
zoo = ['lion','tiger','elephant']
if 'dog' in zoo:
    print('dog is in zoo')
    print('still looking for my dog')
still looking for my dog

The 'list' constructor method

  • We 've seen so far that data objects are constructed from their class special method called 'constructor'

    • For example, integers are constructed by activating int(), float numbers by float(), strings by str().
  • Similarly, list objects in Python are constructed by the list() constructor. We need to pass as argument some kind of sequential structure, for example a string

  • Also , recall that we can use type() to check the type of an object and dir() to get a glimpse at the attributes that the object inherits by its class.

In [37]:
s = 'spam'
alist = list(s)

s = str(alist)
['s', 'p', 'a', 'm']
['s', 'p', 'a', 'm']
  • Going back to string from list can be accomplished with the str() method.
  • In the above example str(alist) returns a string object including not only the original s string characters but also the syntactical list characters (',[, etc.)
  • Find the argument that we should pass to str() to return only the original 'spam' string?
In [27]:
s = '12345'
nlist = list(s)
['1', '2', '3', '4', '5']
In [30]:
alist = [1,2,3,4,5]
<class 'list'> 

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

List vs. String

  • Similarities:

    • Both are sequences: they are ordered collections of 'elementary' items. In the case of strings elementary items are characters (strings of len=1). In the case of list the term 'elementary' simply denotes that the list contains other objects as its items. In fact, these other objects can be compound structures in themselves (for example, other lists).
    • Both are indexed: their items are referenced by an index, which is an integer put in square brackets next to the list/string name.
    • Both are iterable: technically this means that both types include a _next__ method that iterates over the sequencial structure (list or string), returning the next elementary item in order. This allows both lists and strings to be used as iterables in a 'for' loop.
  • Differences:

    • Lists are mutable objects, but strings are immutable: this means that items of a list can be changed 'in place' (in memory places they already occupy) without creating a new list copy in memory. By contrast, to change a string one needs actually to create a new string copy.

. Free learning material
. See full copyright and disclaimer notice