Containers provide a convenient way to store and work on a collection of objects. For instance, a list of files in a folder, pixel values of an image, or properties of datasets like a description, sample size, creation dates, and author, are all examples of collections.

Since you iterate to traverse over their contents, all such containers are called iterable objects, iterables for short. Below we will go through common iterables in Python and learn about their features.

Iterables

  • list and tuple : lists and tuples represent ordered sequences. Both list and tuple are container object types that can store any Python object including other lists and tuples. The difference between the lists and tuples is that lists’ values can be updated and modified after they are created, whereas tuples are immutable and can’t be updated once created.
  • str : string is also an example of ordered immutable sequence of characters. Hence, a lot of methods and functions that work with list and tuple also work with str.

Immutable objects can’t be modified after they are created. str and tuple are examples of immutable sequence types.

Dictionaries and sets are examples of Python containers with unordered collections. You can also store any type of Python object in dictionaries. Sets, on the other hand, are for storing only immutable objects.

  • dict: dictionaries store objects as key-value pairs or key-value maps and do not guarantee the order of the collection unlike lists and tuples.
  • set : sets are also not ordered. They are collections of unique objects and implement the concept of mathematical sets. Sets themselves are mutable but store immutable objects.

Lists, tuples, dictionaries, sets, and strings are examples of most commonly used container types. Python also has other built-in iterable types. If you are interested, see the official documentation for more information on the other container types.

Lists

To initialise an empty list, you can either use [] or call list(). You can also create a list by including your items (objects) in the square brackets, [item1, item2, ...]. You can add and remove items to and from a list, and modify items inside the list after the list’s creation. The following are common functions and methods you would use with lists.

  • list() or []: create an empty list.
  • list(iterator): create a list from another iterator.
  • [item1, item2, item3, ...]: create a list filled with objects item1, item2, item3, etc.
  • .append(item): this method adds a new object item to the list,
  • .extend(iterator): this method extends the list by adding another lists’ or iterator’s items to a list,
  • LIST1 + LIST2 + ...: adding lists with + concatenates the lists into a new (longer) list,
  • len(LIST) : len takes in a list LIST as an input argument and returns the list’s length, number of items in a list.

I added a dot . in front of instance method names to differentiate them from regular function names like len.

An index of an item in a list represents its position within the list. You can use the indices to access and update the list’s items.

  • Indexes start at 0. E.g., let’s create and modify an array with these items:
Index 0 1 2
Value 'apple' 'banana' 'cherry'
  • You can also use negative indices to access and update items by counting from the end of the list. -1 refers to the last item in the list:
Index -3 -2 -1
Value 'apple' 'banana' 'cherry'

Remember that (positive) indexing starts with zero and fruits[len(fruits)] will results in an error as the last index is len(fruits)-1.

  • .pop() method removes and returns the last element of the list, if an optional index argument is given .pop(index) will pop an element at the given index.

pop, append, and extend are instance methods. This means that you call them on each instance of a list object. E.g., fruits is an instance of a list and you call its methods with fruits.append(...), fruits.pop(...), and fruits.extend([...]).

Access, update, or copy a portion of a list by slicing the list with optional start (inclusive) and stop (exclusive) indices, and a step size.

  • LIST[:] refers to all items of the list LIST,
  • LIST[s:] refers to all items starting from the index=s inclusive of s,
  • LIST[:e] refers to all items before but not including index=e (excluding e),
  • LIST[::n] refers to every item with n step size (default step size is 1),
  • LIST[s:e:n] combines start, end, and step.
  • For slices with [s:], [:e], and [:], lengths of two sides of the assignment do not need to be the same when you are using slices or iterables for assignment. The length of a list is automatically adjusted for the new values. E.g., below we can assign a 5-element list to a 2-element slice, the list is automatically expanded in this case.

N*[...] is equivalent to adding or concatenating a list to itself N times. E.g., ['melon']*5 results in ['melon', 'melon', 'melon', 'melon', 'melon'].

  • You can use del function with slices to delete contents of a list.

To clear all elements of the list you can either use del fruits[:] or fruits.clear(). You can learn more about list methods from the documentation.

  • For lists, slices return a copy of a portion of a list when slices are used as values for assignment.

In Python, is checks the object identity. The identity statement returns True if two objects are the same objects, and False otherwise. Identity is different from == which checks for equality (of values).

In the code above, we assigned a second name to the fruits list, both other and fruits refer to the same list. This is verified by running print(fruits is other).

Tuples

As mentioned above, tuples are also ordered sequences of objects similar to lists. Compared to lists, you can not modify a tuple after its creation. Hence, tuples don’t have methods for appending or extending tuple instances.

  • Use ( item1, item2, ...) to create a new tuple with given items.
  • To add a new item, extend, or concatenate tuples you need to create a new tuple object.
  • You can also create a tuple with a single item by including a comma in (item,), Python otherwise ignores the parentheses.
  • You can omit the parentheses when creating tuples with multiple items, and use item1, item2,.... But, I suggest keeping the surrounding parentheses for readability and to avoid bugs. E.g., try removing parentheses around the ('cherry', 'durian') below, you will get an error.

When you print a tuple, print shows items surrounded by parentheses ( and ).

To create an empty tuple, use () or tuple(). Also, you can use tuple(ITERABLE) to convert an input list or other iterable into a tuple object.

  • You can get slices of a tuple using [start:stop:step] similar to the lists.

Strings

You can use indexing and slicing to access and obtain substrings of a string just like lists and tuples. str objects are immutable and you can’t modify a string after creating it.

For convenience, str objects have instance methods for spliting, joining, and modifying an existing string by creating new strings and lists of strings.

  • .replace(old, new): replaces a substring old with a new string new.
  • .split(sep): splits a string into a list of substrings using the separator sep. When used without an input, split(), or with split(None), the method will split a string on any whitespace character, e.g., new line, tab, spaces, etc.
  • .join([string1, string2, ...]): concatenate strings stored as a list or any other iterable using a delimeter string, e.g., " ".join(...) will join input list of strings with space as a delimeter (separator).

For more information on string methods, see official documentation.

Dictionaries

dict relies on unique keys to index, create, access, and update its values.

  • Create a new dictionary using curly braces, e.g., {} (empty dictionary), {key1: item1, key2: item2, ...}, or use dict(key1=value1, key2=value2, ...). The latter requires all keys to be strings, see below for another method with dict().
  • Keys must be hashable types. This means keys’ types should be immutable and should support hashing methods. int, tuple, and string are commonly used types for dictionary keys as they are immutable and support hashing.
Key 'name' 'occupation'
Value 'Bob' 'Builder'
  • If you have an iterator object with key-value pairs, e.g., a list of tuples [(key1, value1), (key2, value2), ...], you can use the iterator as an argument to the dict() constructor to create a new dictionary.
  • To add a new key-value pair to an existing dict, or modify a value of an already present key just assign the value to the key.
  • To access the values, use the key as an index to a dict object. If the key is not in the dictionary, you will get KeyError error.
  • Alternatively, use .get(key) instance method to get the value for a given key. If the key is not in a dictionary .get(key) returns None. Also, .get accepts an optional default value which is returned instead of None when the key is absent.

dict also allows access to their keys and values via instance methods:

  • .keys(): returns iterator containing dictionary’s keys,
  • .values(): returns iterator with the values, and
  • .items(): returns items iterator as key-value pairs.

Keys, values, and items can be easily converted to other iterator types. E.g., If you need to use indices or slices on the keys, values, or items, list(keys) produces (indexed) list of keys.

Sets

Sets are convenient and highly efficient for removing duplicates, joining and finding unique or shared items using set operations like union, intersection, and difference. Sets are also efficient when checking membership, i.e., when checking if the item is in the set, especially when working with large lists of items.

You may think of a set as a dictionary with only keys and no values.

  • Create a set with {item1, item2, ...} inside the curly barces. Alternatively, use set(iterable) to convert an iterable object with immutable items to a set object.
  • .add(item) adds an item to an existing set.
  • .update(iterable) add items from an iterable to an existing set.
  • first.union(another) concatenates (joins) two sets first and another. This creates a new set with unique items from the two sets.
  • .remove(item) deletes an item from a set.
  • .pop(item) pops the item from the set, i.e., removes the item from the set and returns it.
  • .clear() deletes all items from a set.

Membership Testing

You can test if a value or key is in (or not in) an iterable using in.

  • For str, list, tuple, and set, the in keyword tests whether a value is present in a collection.
  • For dict, in tests the keys in a dictionary.
  • To test dictionary values, you can use in together with dict.values or dict.items() methods.

Exercises


E1: Use slicing to obtain a new tuple with with every 2nd item of an original tuple excluding the last item. I.e., get a slice with ('apple', 'durian').


E2: Fix this code to hide the “word”.

  • In the below, s_new censors the word “Password” as well as the word “word”. Verify that by running the code.
  • Modify the replace command to censor only the “word” part.