**Python Programming Fundamentals for Class 11 and 12 – Data Structures**

A data structure is a group of data elements grouped together under one name. Python’s data structures are very intuitive from syntax point of view, and they offer a large choice of operations. This chapter tries to put together the most common and useful information about various data structures. Some of the Python’s data structures that are discussed in this book are list, tuple, set, and dictionary.

List

Python has a number of built-in types to group together data items. The most versatile is the list, which is a group of comma-separated values (items) between square brackets. List items need not to be of same data type.

>>> a=[1 spam', 'eggs', 100, 1234] >>> a ['spam', 'eggs', 100, 1234]

Python allows adding a trailing comma after last item of list, tuple, and dictionary, . There are several reasons to allow this:

When the list, tuple, or dictionary elements spread across multiple lines, one needs to remember to add a comma to the previous line. Accidentally omitting the comma can lead to error that might be hard to diagnose. Always adding the comma avoids this source of error (example is given below).

If comma is placed in each line, they can be reordered without creating a syntax error.

The following example shows the consequence of missing a comma while creating list.

>>> a=[ 'hi', 'hello' 'bye', 'tata', ] >>> a ['hi', 'hellobye', 'tata']

This list looks like it has four elements, but it actually contains three: ‘hi’, ‘hellobye’ and ‘ tata’. Always adding the comma avoids this source of error.

**List creation**

List can be created in many ways.

**Using square brackets**

As discussed before, most common way of creating a list is by enclosing comma-separated values (items) between square brackets. Simply assigning square bracket to a variable creates an empty list.

>>> a=[] >>> a [] >>> type(a) <type 'list'>

**Using other lists**

A list can also be created by copying a list or slicing a list.

>>> a=['spam', 'eggs', 100, 1234] >>> b=a[:] >>> b ['spam', 'eggs', 100, 1234] >>> c=a[l:3] >>> c ['eggs', 100]

**List comprehension**

List comprehension provides a concise way to create list. A list comprehension consist of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a sub-sequence of those elements that satisfy a certain condition. For example, creating a list of squares using an elaborate approach is as follows:

>>> squares=[] >>> for x in range(10): ... squares.append(x**2) >>> squares [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

The same can be obtained using list comprehension as:

squares=[x**2 for x in range(10)] >>> squares [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Alternatively, it can also be obtained using map () built-in function:

squares=map(lambda x: x**2,range(10)) >>> squares [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

The following list comprehension combines the elements of two lists if they are not equal:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x!=y] [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

and it’s equivalent to:

>>> combs=[] >>> for x in [1,2,3]: ... for y in [3,1,4]: ... if x!=y: ... combs.append((x,y)) >>> combs [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

**Using built-in function**

List can also be created using built-in function list (). The list ( [iterable] ) function return a list whose items are the same and in the same order as iterable items. The iterable can be either a sequence, a container that supports iteration, or an iterator object. If iterable is already a list, a copy is made and returned. If no argument is given, a new empty list is returned.

>>> list(('hi', 'hello','bye')) ['hi', 'hello', 'bye'] >>> list('hello') ['h', 'e', 'l', 'l', 'o'] >>> list ( (10,50,)) [10, 50] >>> list() []

**Accessing list elements**

Like string indices, list indices start at 0. To access values in list, use the square brackets with the index or indices to obtain a slice of the list.

>>> a=['spam','eggs',100,1234] >>> a [ 0 ] 'spam' >>> a [ 0 ] [1] 'p' >>> a[1:3] . [ ' eggs ' , 100 ]

**Updating list elements**

It is possible to change individual or multiple elements of a list:

>>> a= [' spam', 'eggs', 100, 1234] >>> a[0]='filter' >>> a ['filter', 'eggs', 100, 1234] >>> a[2:4]=455,56858 >>> a ['filter', 'eggs', 455, 56858]

The items of list can be updated by the elements of another iterable (list, tuple).

>>> a=[66.25,333,333,1,1234.5] >>> b=[ 'hi', 'bye' ] >>> a [ 2 : 4 ] =b >>> a [66.25, 333, 'hi', 'bye', 1234.5] >>> a= [66.25,333,333, 1, 1234.5] >>> b=('hi','bye') »> a [ 2 : 4 ] =b >>> a , [66.25, 333, 'hi', 'bye', 1234.5] >>> a=[66.25,333,333,1,1234.5] >>> b=['hi','bye'] >>> a[1:4:2]=b >>> a [66.25, 'hi', 333, 'bye', 1234.5]

It is also possible to insert elements in a list.

>>> a=['spam','eggs',100,1234] >>> a[1:1] = [ 'chair'] >>> a ['spam', 'chair', 'eggs', 100, 1234] >>> a[1:1]=['hello','bye'] >>> a ['spam', 'hello', 'bye', 'chair', 'eggs', 100, 1234]

To insert a copy of list at the beginning of itself:

>>> a=['spam','eggs',100,1234] >>> a[:0]=a >>> a ['spam', 'eggs', 100, 1234, 'spam', 'eggs', 100, 1234]

There are various methods of list object for updating list, which are discussed in section 4.1.9.

**Deleting list elements**

To remove a list element, one can use either the del statement (if you know the element index to delete) or remove () method (if you do not know the element index, but the element itself, discussed in section 4.1.9). The following example depicts deletion of an element using del statement.

>>> a=['spam', 'eggs100,1234] >>> del a[1] >>> a ['spam', 100, 1234]

The del statement can also be used to explicitly remove the entire list.

>>> a=['spam','eggs',100,1234] >>> del a >>> a Traceback (most recent call last): File "", line 1, in NameError: name 'a' is not defined

The following is an interesting case of del statement:

>>> a=['spam','eggs',100,1234] >>> del a[1],a[1] >>> a ['spam', 1234]

It should be noted that the same index is deleted twice. As soon as an element is deleted, the indices of succeeding elements are changed. So deleting an index element n times, would actually delete n elements.

It is also possible to delete multiple items of a list.

>>> a=['spam','eggs',100,1234] >>> a [1:3] = [] >>> a ['spam', 1234 ]

**Swapping lists**

There might be a scenario in which multiple lists needs to be swapped among themselves. This is can done easily using multiple assignments expression.

>>> a=[10,20,30] >>> b=[40,50,60] ’ >>> c= [70, 80, 90] >>> a,b,c=c,a,b >>> a [70, 80, 90] >>> b [10, 20, 30] >>> c [40, 50, 60]

**Looping techniques**

List can also be used in iteration operation, for example:

>>> for a in [4,6,9,2]: print a 4 6 9 2 >>> for a in [4,6,9,2]: print a, 4 6 9 2

When looping through a sequence, the position index and corresponding value can be retrieved at the same time using the enumerate () function.

>>> for i,v in enumerate(['tictactoe']): ... print i, v 0 tic 1 tac 2 toe

To loop over two or more sequences at the same time, the entries can be paired with the zip () function.

>>> questions=['name','quest','favorite color'] >>> answers= [ ' lancelot' , ' the holy grailblue ' ] *. >>> for q,a in zip(questions,answers): ... print 'What is your {0}? It is {1}.'.format(q,a) What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue.

While iterating a mutable sequence, if there is a need to change the sequence (for example to duplicate certain items), it is recommended to make a copy of the sequence before starting iteration. Looping over a sequence does not implicitly make a copy. The slice notation makes this especially convenient.

>>> words=['cat','window','defenestrate'] >>> for w in words[:]: ... if len(w)>6: words.insert(0,w) >>> words ['defenestrate', 'cat', 'window', 'defenestrate']

**Nested list**

It is possible to nest lists (create list containing other lists), for example:

>>> q= [2,3] >>> p=[1,q,4] >>> len(p) 3 >>> P [ 1 ] [2, 3] >>> p [1] [0] 2 >>> p[1].append('xtra') >>> p [1, [2, 3, 'xtra']', 4] >>> q [2, 3, 'xtra']

Note that in the last example, p [1] and q refer to the same object, which can cross-checked using id () built-in function.

>>> id(q) 104386192 >>> id(p[l] ) 104386192

**Some list operations**

Some of the list operations supported by Python are given below.

**Concatenation**

List concatenation can be carried out using + operator.

>>> [1,2,3]+['hi','hello'] [1, 2, 3, 'hi', 'hello']

**Repetition**

The * operator can be used to carry out repetition operation.

>>> ['Hey']*3 ['Hey', 'Hey', 'Hey']

**Membership operation**

List also supports membership operation i.e. checking the existence of an element in a list.

>>> 4 in [6,8, 1,3,5,0] False >>> 1 in [6,8,1,3,5,0] True

**Slicing operation**

As list is a sequence, so indexing and slicing work the same way for list as they do for strings. All slice operations return a new list containing the requested elements:

>>> a=['spam','eggs100,1234] >>> a[2] 100 >>> a[-2] 100 >>> a [ 1: 3 ] [ 'eggs' , 100] >>> a[:] ['spam', 'eggs', 100, 1234]

List slicing can be in form of steps, the operation s [ i : j : k ] slices the list s from i to j with step k.

>>> squares=[x**2 for x in range(10)] >>> squares [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196] >>> squares[2:12:3 ] [4, 25, 64, 121]

Slice indices have useful defaults, an omitted first index defaults to zero, an omitted second index defaults to the size of the list being sliced.

>>> squares=[x**2 for x in range(10)] >>> squares [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144,,.169, 196] >>> squares[5:] [25, 36, 49, 64, 81, 100, 121, 144, 169, 196] >>> squares[:5] [0, 1, 4, 9, 16]

**List methods**

Below are the methods of list objects.

list.append(x)

Add an item to the end of the list. It is same as list [len (list) : len (list) ] = [x].

>>> a=[66.25,333,333, 1, 1234.5] >>> a.append(45) >>> a [66.25, 333, 333, 1, 1234.5, 45] >>> a=[66.25,333,333,1, 1234.5] >>> a[len(a):len(a)]=[45] >>> a [66.25, 333, 333, 1, 1234.5, 45]

list.extend(L)

Extend a list by appending all the items of a given list. It is same as list [len (list) : len (list) ] =L.

>>> a=[66.25,333,333,1,1234.5] >>> b= [ 7.3,6.8 ] >>> a.extend(b) >>> a [66.25, 333, 333, 1, 1234.5, 7.3, 6.8] >>> a= [66.25,333,333, 1, 1234.5] >>> b= [ 7.3,6.8 ] >>> a[len(a):len(a)]=b >>> a [66.25, 333, 333, -1, 1234.5, 7.3, 6.8]

list.insert(i,x)

Insert an item at a given position in the list. The first argument i is the index before which an item x need to be inserted. It is same as list [i : i] = [x].

>>> a=[66.25,333,333,1,1234.5] >>> a.insert(2,5.7) >>> a [66.25, 333, 5.7, 333, 1, 1234.5] >>> a=[66.25,333,333, 1,1234.5] >>> a [2 : 2] = [5.7] >>> a [66.25, 333, 5.7, 333, 1, 1234.5]

list.index(x [,i [,j]])

Return the index in the list of the first occurrence of item x. In other words, it returns the smallest index k such that list [k] ==x and i<=k< j. A ValueError exception is raised in absence of item x.

>>> a=[66.25,333,333,1,1234.5] >>> a.index(333) 1

list.remove(x)

Remove the first item from the list whose value is x. An error (ValueError exception) occur in absence of item x. It is same as del list [ list. index (x) ].

>>> a=[66.25,333,333,1,1234.5] >>> a.remove(333) >>> a [66.25, 333, 1, 1234.5] >>> a=[66.25,333,333, 1,1234.5] >>> del a[a.index(333)] >>> a [66.25, 333, 1, 1234.5]

list.pop([i])

Remove the item at the given position i in the list, and return it. If no index is specified (defaults to -1), pop () removes and returns the last item in the list.

>>> a=[66.25, 333,333, 1, 1234.5] >>> a.pop(3) 1 >>> a [66.25, 333, 333, 1234.5] >>> a.pop() 1234.5 >>> a . [66.25, 333, 333]

list.count(x)

Return the number of times item x appears in the list.

>>> a=[66.25,333,333, 1, 1234.5] >>> a.count(333) 2

list.reverse()

Reverse the element’s position in the list; no new list is returned. It is same as list=list [: : -1 ].

>>> a=[66.25,333,333,1,1234.5] >>> a.reverse() >>> a [1234.5, 1, 333, 333, 66.25] >>> a=[66.25,333,333, 1,1234.5] >>> a=a[::-1] [1234.5, 1, 333, 333, 66.25]

list.sort([cmp[,key[,reverse]]])

Sort the items of the list; no new list is returned. The optional arguments have same meaning as given in sorted () built-in function.

>>> a=[66.25, 333,333,1,1234.5] >>> a.sort() >>> a [1, 66.25, 333, 333, 1234.5] >>> a= [66.25,333, ’ abc ', 333,1, ’ab', 1234.5] >>> a . sort ( ) >>> a [1, 66.25, 333, 333, 1234.5, 'ab', 'abc'] >>> a=[66.25,333,'abc',333,1,'ab',1234.5] >>> a.sort(reverse=True) >>> a ['abc', 'ab', 1234.5, 333, 333, 66.25, 1]

**Using list as Stack**

The list methods make it very easy to use a list as a stack, where the last element added is the first element retrieved (“last-in, first-out” approach). To add an item to the top of the stack, use append (). To retrieve an item from the top of the stack, use pop () without an explicit index. For example:

>>> stack=[3,4,5] >>> stack.append(6) >>> stack.append(7) >>> stack [3, 4, 5, 6, 7] >>> stack.pop() 7 >>> stack [3, 4, 5, 6] >>> stack.pop() 6 >>> stack.pop() 5 >>> stack [3, 4]

**Using list as queue**

It is also possible to use a list as a queue, where the first element added is the first element retrieved (“first-in, first-out”); however, list is not efficient for this purpose. While appending and popping of elements from the end of list are fast, doing inserting and popping from the beginning of a list is slow (because all of the other elements have to be shifted by one).

To implement a queue, use collections . deque which was designed to have fast appends and pops from both ends. For example:

>>> from collections import deque >>> queue=deque(["Eric","John","Michael"]) >>> queue.append("Terry") >>> queue.append("Graham") >>> queue deque(['Eric', 'John', 'Michael', 'Terry', 'Graham']) >>> queue.popleft() 'Eric' >>> queue.popleft() 'John' >>> queue deque(['Michael', 'Terry', 'Graham'])

Tuple

There is also another sequence type- tuple. Tuples is a sequence just like list. The differences are that tuple cannot be changed i.e. tuple is immutable, while list is mutable, and tuple use parentheses, while list use square brackets. Tuple items need not to be of same data type. Also, as mentioned previously, Python allow adding a trailing comma after last item of tuple.

>>> a=('spam','eggs',100,1234) >>> a ('spam', 'eggs', 100, 1234) >>> a=('spam','eggs',100,1234,) >>> a ('spam', 'eggs', 100, 1234)

The above expressions are examples of “tuple packing” operation i.e. the values ‘spam’, ‘eggs’, 100 and 1234 are packed together in a tuple. The reverse operation is also possible, for example:

>>> a1, a2 , a3, a4=a >>> al 'spam' >>> a2 'eggs' >>> a3 100 >>> a4 1234

This is called “sequence unpacking”, and works for any sequence on the right-hand side. Sequence unpacking requires the group of variables on the left to have the same number of elements as the length of the sequence. Note that multiple assignments are really just a combination of tuple packing and sequence unpacking.

>>> a,b=10,20 >>> a 10 >>> b 20

**Tuple creation**

Tuple can be created in many ways. .

**Using parenthesis**

Creating a tuple is as simple as grouping various comma-separated values, and optionally these comma-separated values between parentheses.

>>> a= ('spameggs100,1234) >>> a ('spam', 'eggs', 100, 1234) >>> a=('spam','eggs',100,1234,) >>> a ('spam', 'eggs', 100, 1234) >>> a='spam','eggs',100,1234 >>> a ('spam', 'eggs', 100, 1234) >>> a='spam','eggs',100,1234, >>> a ('spam', 'eggs', 100, 1234)

A tuple with one item is created by a comma after the item (it is not necessary to enclose a single item in parentheses).

>>> a=(10) >>> a 10 >>> type(a) <type 'int'> >>> b= (10, ) >>> b (10, ) >>> type(b) <type 'tuple'> >>> c=10, >>> c (10, ) >>> type(c) <type 'tuple'>

It is also possible to create an empty tuple by assigning parenthesis to a variable.

>>> a=() >>> a 0

**Using other tuples**

A tuple can also be created by copying a tuple or slicing a tuple.

>>> a=('spam','eggs',100,1234) >>> b=a[:] >>> b ('spam', 'eggs', 100, 1234) >>> c=a[l:3] >>> c ('eggs', 100)

**Using built-in function**

Tuple can also be created using built-in function tuple (). The tuple ( [iterable] ) function return a tuple whose items are same and in the same order as items of the iterable. The iterable may be a sequence, a container that supports iteration, or an iterator object. If iterable is already a tuple, it is returned unchanged. If no argument is given, an empty tuple is returned.

>>> tuple(['apple','pineapple','banana']) ('apple', 'pineapple', 'banana') >>> tuple('apple') ('a', 'p', 'p', '1', 'e') >>> tuple(['apple']) ('apple',)

**Accessing tuple elements**

The tuple index start with 0, and to access values in tuple, use the square brackets with the index or indices to obtain a slice of the tuple.

>>> a=('spam','eggs',100,1234) >>> a[0] 'spam' >>> a [ 1 : 3 ] ( 'eggs', 100)

**Update tuple**

Tuple is immutable, so changing element value or adding new elements is not possible. But one can take portions of existing tuples to create a new tuples.

>>> tuplel=(1,2,3) >>> tuple2=('a','b','c') >>> tuple3=tuplel+tuple2 >>> tuple3 (1, 2, 3, 'a', 'b', 'c') >>> tuple3=tuple1[0:2]+tuple2[l:3] >>> tuple3 (1, 2, 'b', 'c')

It is also possible to create tuple which contain mutable objects, such as lists.

>>> a= [1, 2,3] , [4,5,6, 7] >>> a (fl, 2, 3], [4, 5, 6, 7]) >>> a [0] [1]=200 • >>> a ([1, 200, 3], [4, 5, 6, 7])

**Deleting tuple**

Removing individual tuple element is not possible. To explicitly remove an entire tuple, just use the del statement.

>>> a=('spam', 'eggs100,1234) >>> del a

**Swapping tuples**

There might be a scenario in which multiple tuples needs to be swapped among themselves. This is can done easily using multiple assignments expression.

>>> a=(10,20,30) >>> b= (40,50,60) >>> c=(70,80,90) >>> a,b,c=c,a,b >>> a (70, 80, 90) >>> b (10, 20, 30) >>> c (40, 50, 60)

**Looping techniques**

Tuple can also be used in iteration operation, for example:

>>> for a in (4,6,9,2): print a 4 6 9 2 >>> for a in (4,6,9,2): print a, 4 6 9 2

When looping through a sequence, the position index and corresponding value can be retrieved at the same time using the enumerate () function.

>>>for i,v in enumerate ((' tic tac toe ')) : ... print i,v 0 tic 1 tac . 2 toe

To loop over two or more sequences at the same time, the entries can be paired with the zip () function.

>>> questions=('name','quest','favorite color') >>> answers=('lancelot', 'the holy grail', 'blue') >>> for q,a in zip(questions,answers): ... print 'What is your {0}? It is {1}.'.format(q,a) ... What is your name? It is lancelot. What is your quest? It is the holy grail. What is your favorite color? It is blue.

**Nested tuple**

It is possible to create nested tuples.

>>> q=(2,3) >>> r=[5,6] >>> p= (1, q, 4, r) >>> len(p) 4 >>> p[1] (2, 3) >>> p [1] [0] 2 >>> p [ 3 ] [5, 6] >>> p (1, (2, 3), 4, [5, 6])

Note that in the last example, p [ 1 ] and q refer to the same object, also p [ 3 ] and r refer to the same object.

**Some tuple operations**

Some of the tuple operations supported by Python are given below.

**Concatenation**

Tuple concatenation can be carried out using + operator.

>>> (1, 2,3) + ( 'hi', 'hello' ) (1, 2, 3, 'hi', 'hello')

**Repetition**

The * operator can be used to carry out repetition operation.

>>> ('Hey',)*3 ('Hey', 'Hey', 'Hey')

**Membership operation**

Tuple also supports membership operation i.e. checking the existence of an element in a tuple.

>>> 4 in (6,8,1,3,5,0) False >>> 1 in (6, 8,1,3,5,0 ) True

**Slicing operation**

As tuple is a sequence, so indexing and slicing work the same way for tuple as they do for strings. All slice operations returns a new tuple containing the requested elements:

>>> a=('spam', 'eggs 1, 100, 1234) >>> a[2] 100 >>> a[-2] 100 >>> a [ 1: 3 ] ('eggs', 100) >>> a[:] ('spam', 'eggs', 100, 1234)

Tuple slicing can be in form of steps, the operation s [i : j : k] slices the tuple s from i to j with step k.

>>> squares= ( 0, 1,4,9,16,25,36,49,64,81,100,121,144,169,196) >>> squares[2:12:3] (4, 25, 64, 121)

Slice indices have useful defaults, an omitted first index defaults to zero, an omitted second index defaults to the size of the tuple being sliced.

>>> squares= (0, 1, 4,9,16,25,36,49,64, 81,100,121,144,169,196) >>> squares[5:] (25, 36, 49, 64, 81, 100, 121, 144, 169, 196) >>> squares [ : 5 ] (0, 1, 4, 9, 16)

Set

A set is an unordered collection with no duplicate elements. Basic uses include membership testing, eliminating duplicate entries from sequence, mathematical operations like union, intersection, difference, symmetric difference etc. As mentioned in chapter 2, sets are of two types: set (mutable set) and frozenset (immutable set).

>>> a=set(['spam','eggs',100,1234]) >>> a set(['eggs', 100, 1234, 'spam']) >>> a=set('abracadabra') >>> a set(['a', 'r', 'b', 'c', 'd']) >>> a=frozenset(['spam','eggs’,100,1234]) >>> a frozenset(['eggs', 100, 1234, 'spam'])

Being an unordered collection, sets do not record element position or order of insertion. Accordingly, sets do not support indexing, slicing, or other sequence-like behavior.

**Set creation**

A set can be created in many ways.

**Using curly braces**

Non-empty set (not frozenset) can be created by placing a comma-separated list of elements within braces. Curly braces cannot be used to create an empty set, because it will create an empty dictionary that will be discussed in the next section.

>>> {'spam','eggs',100, 1234} set([1234, 100, 'eggs', 'spam'])

**Set comprehension**

Python also supports set comprehension:

>>> a={x for x in 'abracadabra' if x not in 'abc'} >>> a set(['r', 'd'])

**Using built-in function**

The built-in functions set () and frozenset () are used to create set and frozenset, respectively, whose elements are taken from iterable. If iterable is not specified, a new empty set is returned.

>>> a=set(('spam','eggs',100,1234)) >>> a set(['eggs', 100, 1234, 'spam']) >>> set () set ( [ ] ) >>> a=frozenset(('spam','eggs',100,1234)) >>> a frozenset(['eggs', 100, 1234, 'spam']) >>> frozenset() frozenset([]) >>> set('abc')==frozenset('abc') True

**Deleting set**

To explicitly remove an entire set, just use the del statement.

>>> ss=set('abracadabra') >>> ss set(['a', 'r', 'b', 'c', 'd']) >>> del ss >>> ss Traceback (most recent call last): File "", line 1, in NameError: name 'ss' is not defined

**Looping techniques**

It is also possible to iterate over each element of a set. However, since set is unordered, it is not known which order the iteration will follow.

>>> ss=set('abracadabra') >>> ss set(['a', 'r', 'b', 'c', 'd']) >>> for item in ss: ... print item a r b c d

**Membership operation**

Set also support membership operation.

a=set('abracadabra') >>> a set(['a', 'r', 'b', 'c', 'd']) >>> 'r' in a True >>> 'rrr' not in a True >>> a^frozenset ( ' abracadabra ' ) >>> a frozenset(['a', 'r', 'b', 'c', 'd"]) >>> 'r' in a True >>> 'rrr' not in a True

**Set methods**

Below are the methods of both set and f rozenset objects. Note that the non-operator versions of these methods accepts any iterable as an argument, while their operator based counterparts require their arguments to be sets (set and frozenset).

isdisjoint(other)

Return True, if the set has no elements in common with other. Sets are disjoint, if and only if their intersection is the empty set.

>>> s1=set([5,10,15,20]) >>> s2=set([30,35,40]) >>> si.isdisjoint(s2) True >>> sl=frozenset ( [5,10,15,20]) >>> s2=frozenset([30,35,40]) >>> si.isdisjoint(s2) True >>> sl=set([5,10,15,20]) >>> s2=frozenset([30,35,40]) >>> si.isdisjoint(s2) True

issubset(other)

Test whether every element in the set is in other.

>>> s1=set ( [5,15]) >>> s2=set([5,10,15,20]) >>> si.issubset(s2) . True >>> si.issubset((5,10,15,20)) True >>> sl=frozenset([5,15]) >>> s2=frozenset([5,10,15,20]) >>> si.issubset(s2) True >>> si.issubset((5,10,15,20)) True

The operator based version of the the above method is

set <=other. >>> s1=set ( [5,15]) >>> s2=frozenset([5,10,15,20]) >>> s1<=s2 True

The operator based version

set>> s1=set([5,15]) >>> s2=frozenset([5,10,15,20]) >>> sl>> s1=set ( [5,15]) >>> s2=set( [5,10,15,20]) >>> s2.issuperset(s1) True >>> s2.issuperset((5,15)) True >>> s1=frozenset([5,15]) >>> s2=frozenset([5,10,15,20]) >>> s2.issuperset(sl) True >>> s2.issuperset((5,15))

The operator based version of the the above method is set>=other.

>>> s1=set([5,15]) >>> s2=frozenset([5,10,15,20]) >>> s1>=s2 False

The operator based version set>other test whether the set is a proper superset of other, that is,

set>=other and set!-other.

>>> s1=set([5,15]) >>> s2=frozenset( [5,10,15,20]) >>> s1>> s1=set ( [5,15]) >>> s2=[15, 20,25] >>> s3=frozenset([30,35,40]) >>> s1.union(s2,s3) set ( [35, 20, 5, 40, 25, 30, 15]) ;

The operator based version of the the above method is set | other . ..

>>> s1=set([5,15]) >>> s2=set([15,20,25]) >>> s3=frozenset([30,35,40]) >>>s 1 | s2 | s3 set ([ 35, 20, 5, 40, 25, 30, 15])

intersection(other, …)

Return a new set with elements common to the set and all others .

>>> s1=set([5,10,15]) >>> s2=[15,20,25,10] >>> s3=frozenset([30,15,35,40,10]) >>> s4=(40,50,10,15,20) >>> si.intersection(s2,s3,s4) set ([10, 15])

The operator based version of the the above method is set&other . ..

>>> s1=set([5,10,15]) >>> s2=set([15,20,25,10]) >>> s3=frozenset([30,15,35,40,10]) >>> s4=frozenset([40,50,10,15,20]) >>> s1&s2&s3&s4 set([10, 15])

difference(other, …)

Return a new set with elements in the set that are not in the others.

>>> s1=set([5,10,15]) >>> s2=[15,20,25,10] >>> s3=frozenset( [30,-15, 35, 40, 10] ) >>> S4=(40,50,10,15,20) >>> s3.difference(si,s2,s4) frozenset([35, 30])

The operator based version of the the above method is set-other-. ..

>>> s1=set([5,10,15]) >>> s2=set([15,20,25,10]) >>> s3=frozenset([30,15,35,40,10]) >>> s4=frozenset([40,50,10,15,20]) >>> sl-s2-s3-s4 set( [5] ) >>> s3-sl-s2-s4 frozenset([35, 30])

symmetric_difference(other)

Return a new set with elements in either the set or other but not both.

>>> s1=set([5,10,15]) >>> s2=[15, 20,25, 10] >>> si.symmetric_difference(s2) set([25, 20, 5])

The operator based version of the the above method is set Aother.

>>> s1=set([5,10,15]) >>> s2=frozenset([15,20,25,10]) >>> s1^s2 set([25, 20, 5]) >>s2^s1 frozenset([25, 20, 5])

copy()

Return a copy of the set.

>>> s=set([5,10,15,20]) >>> a=s.copy() >>> a set ([10, 20, 5, 15]) >>> s=frozenset( [5,10,15,20]) >>> a=s.copy() >>> a frozenset([ 10, 20, 5, 15])

The following methods are available for set and do not apply to immutable instances of f rozenset.

update(other, …)

Update the set, adding elements from all others.

>>> s1=set([5,15]) >>> s2= (15, 20, 25) >>> s3=frozenset([30,35,40]) >>> si.update(s2,s3) >>> si set ( [35, 20, 5, 40, 25, 30, 15])

The operator based version of the the above method is set | =other | . ..

>>> s1=set([5,15]) >>> s2=set([15,20,25]) >>> s3=frozenset([30,35,40]) >>> si | =s2 | s3 >>> si set( [35, 5, 40, 15, 20, 25, 30])

intersection_update(other, …)

Update the set, keeping only elements found in it and all others.

>>> s1=set([5,10,15]) >>> s2= [15,20,25, 10] >>> s3=set([30,15,35,40,10]) >>> s4=(40,50, 10, 15,20) >>> si.intersection_update(s2,s3,s4) >>> si set( [10, 15])

The operator based version of the the above method is set&=other& . ..

>>> sl = set( [5,10,15] ) >>> s2 = set( [ 15, 20,25,10]) >>> s3=frozenset([30,15,35,40,10]) >>> s4=frozenset([40,50,10,15,20]) >>> sl&=s2&s3&s4 >>> si set ( [ 10, 15])

difference_update(other, …)

Update the set, removing elements found in others.

>>> sl=frozenset([5,10,15]) >>> s2=[15, 20,25, 10] >>> s3=set([30,15,35,40,10]) >>> s4=(40, 50, 10, 15,20) >>> s3.difference_update(si, s2, s4) >>> s3 set( [35, 30])

The operator based version of the the above method is set-=other | . ..

>>> sl=frozenset([5,10,15]) >>> s2=frozenset([15,20,25,10]) >>> s3=set ( [30, 15, 35, 40, 10] ) >>> s4=frozenset([40,50,10,15,20]) >>> s3-=sl|s2|s4 >>> s3 set( [35, 30])

symmetric_difference_update(other)

Update the set, keeping only elements found in either set, but not in both.

>>> sl=set([5,10,15]) >>> s2=[15,20,25,10] >>> si.symmetric_difference_update(s2) >>> si set( [25, 20, 5])

The operator based version of the the above method is set A=other.

>>> sl=set([5,10,15]) >>> s2=frozenset ([15,20,25, 10'] ) >>> slA=s2 >>> si set([25, 20, 5])

add(elem)

The method adds element elem to the set.

>>> s=set([5,10,15,20]) >>> s.add(25) >>> s set ( [25, 10, 20, 5, 15])

remove(elem)

Remove element elem from the set. Raises KeyError, if elem is not contained in the set.

>>> s=set([5,10,15,20]) >>> s.remove(15) >>> s set( [10, 20, 5]) >>> s=set([5,10,15,20]) >>> s.remove(100) Traceback (most recent call last): File "", line 1, in KeyError: 100

discard(elem)

Remove element elem from the set if it is present. It is difference from remove () in a way that it does not raise KeyError if elem is not present in the set.

>>> s=set([5,10,15,20]) >>> s.discard(15) >>> s set( [ 10, 20, 5]) >>> s.discard(100) >>> s set([10, 20, 5])

pop ()

Remove and return an arbitrary element from the set. Raises KeyErro^r, if the set is empty.

>>> s=set([5,10,15,20]) >>> s.pop() 10 >>> s set ( [20, 5, 15]) >>> s.pop() 20 >>> s set ( [5, 15])

clear()

Remove all elements from the set.

>>> s=set([5,10,15,20]) >>> s.clear() >>> s set ( [ ] )

Dictionary

Another useful mutable built-in type is “dictionary”. A dictionary as an unordered group of comma separated “key : value” pairs enclosed within braces, with the requirement that the keys are unique within a dictionary. The main operation on a dictionary is storing a value corresponding to a given key and extracting the value for that given key. Unlike sequences, which are indexed by a range of numbers, dictionary is indexed by key (key should be of immutable type, strings and numbers can always be keys). Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. List cannot be used as keys, since lists are of mutable type. Also, as mentioned previously, Python allow adding a trailing comma after last item of the dictionary.

>>> a={'sape':4139,'guido':4127,'jack':4098} >>> a {'sape': 4139, 'jack': 4098, 'guido': 4127} >>> a [ 'jack'] 4098 >>> a={'sape':4139,'guido':4127,'jack':4098,} >>> a {'sape': 4139, 'jack': 4098, 'guido': 4127}

**Dictionary creation**

Dictionary can be created in many ways.

**Using curly braces**

Placing a comma-separated record of key-value pairs within the braces adds initial key-value pairs to the dictionary; this is also the way dictionaries are written as output.

>>> a={'sape':413 9, 'guido':4127, 'jack':4098} >>> a , {'sape': 4139, 'jack': 4098, 'guido': 4127}

A pair of braces creates an empty dictionary.

>>> a={ } >>> a { } >>> type(a) <type 'dict'>

**Dictionary comprehension**

Dictionary comprehension provides a concise way to create dictionary.

>>> {x: x**2 for x in (2,4,6)} {2: 4, 4: 16, 6: 36}

**Using built-in function**

Dictionary can also be created using built-in function diet (). Consider the following example using diet (), which returns the same dictionary { “one” : 1, “two” : 2, “three” : 3 }:

>>> a=dict(one=l,two=2,three=3) >>> b={'one':1,'two':2,'three':3} >>> c=dict(zip(['one'two', 'three'], [1,2,3])) >>> d=dict([('two',2),('one',1),('three',3)]) >>> e=dict({'three':3,'one':1,'two':2}) >>> a==b==c==d==e True

**Accessing dictionary elements**

To access a dictionary value, use key enclosed within square bracket. A KeyError exception is raised if the key is not present in the dictionary.

>>> a={'sape' :413 9, 'guido' :412 7, 'jack' :4098} >>> a['guido'] . 4127

**Updating dictionary elements**

It is possible to add new item in a dictionary and can also change value for a given key.

>>> a={'sape':4139,'guido':4127,'jack':4098} >>> a['mike']=2299 # Add new item >>> a['guido']=1000 # Update existing item >>> a {'sape': 4139, 'mike': 2299, 'jack': 4098, 'guido': 1000}

It is also possible to update a dictionary with another dictionary using update () method (discussed later).

**Deleting dictionary elements**

To remove a dictionary item (key-value pair) or the entire dictionary, one can use the del statement. To remove all items (resulting an empty dictionary), clear () method (discussed later) can be used.

>>> a={'sape':4139,'guido':4127,'jack':4098} >>> del a['guido'] >>> a {'sape': 4139, 'jack': 4098} >>> del a >>> a Traceback (most recent call last): File "", line 1, in NameError: name 'a' is not defined

**Membership operation**

Dictionary support membership operation i.e. checking the existence of a key in the dictinary.

>>> a={'sape':4139,'guido':4127,'jack':4098} >>> 'jack' in a True >>> 'tom' not in a True >>> 4127 in a False

**Looping techniques**

When looping through dictionary, the key and corresponding value can be retrieved at the same time using the iteritems () method.

>>> a={'sape' :413 9, 'guido' :412 7, 'jack' :4 0 9 8 } >>> for k,v in a.iteritems(): ... print k,v sape 4139 jack 4098- guido 4127

**Dictionary methods**

The following are some dictionary methods supported by Python.

diet.clear()

Removes all items from the dictionary.

>>> a={'Name':'Zara','Age':7} >>> len(a) 2 >>> a.clear() >>> len(a) 0

dict.copy()

Returns a copy of dictionary.

>>> dictl={'Name':'Zara','Age':7} >>> dict2=dict1.copy() >>> dict2 {'Age': 7, 'Name': 'Zara'} .

diet.fromkeys(seq[,value])

Create a new dictionary with keys from seq and values set to value (default as None).

>>> seq=('name','age','gender') >>> a=dict.fromkeys(seq) >>> a {'gender': None, 'age': None, 'name': None} >>> a=a.fromkeys(seq,10) >>> a {'gender': 10, 'age': 10, 'name': 10}

dict.get(key[,default])

Return the value for key, if key is in the dictionary, else default. If default is not given, the

default is None.

>>> a={'Name':'Zara','Age':7} >>> a.get('Age') 7 >>> a.get('Gender','Never') 'Never' >>> print a.get('Gender') None

dict.has_key(key)

Test for the presence of key in the dictionary. Returns True, if key is present in dictionary, otherwise False.

>>> a={'Name':'Zara','Age':7} >>> a.has_key('Age') True >>> a.has_key('Gender') False

diet.items()

Returns a list of dictionary’s key-value tuple pairs.

>>> a= { ' Name ' : ' Zara ' , ' Age ' : 7 } >>> a.items() [('Age', 7), ('Name', 'Zara')]

diet.iteritems()

Returns an iterator over the dictionary’s key-value pairs.

>>> a={ ' Gender ' : ' Female ' , 'Age ' : 7, ' Hair color ' :None, ' Name ' : ' Zara ' } >>> for b in a.iteritems(): ... print '{0} {1}'.format(b[0],b[1]) Gender....Female Age......7 Hair color.......None Name......Zara

dict.iterkeys()

Returns an iterator over the dictionary’s keys.

>>> a={'Gender':'Female','Age':7,'Hair color':None,'Name':'Zara'} >>> for b in a.iterkeys(): ... print b Gender Age Hair color Name

dict.itervalues()

Returns an iterator over the dictionary’s values.

>>> a={’Gender':'Female','Age':7,'Hair color':None,'Name':'Zara'} >>> for b in a.itervalues(): ... print b Female 7 None Zara

dict.keys()

Returns list of dictionary keys.

>>> a={'Name':'Zara','Age':7} >>> a.keys() ['Age', 'Name']

dict.pop(key[,default])

If key is in the dictionary, remove it and return its value, else return default. If default is not it given and key is not in the dictionary, a KeyError is raised.

>>> a={'Gender':'Female','Age':7,'Hair color':None,'Name':'Zara'} >>> a.pop('Age',15) 7 >>> a.pop('Age',15) 15 >>> a {'Gender': 'Female', 'Hair color': None, 'Name': 'Zara'}

dict.popitem() .

Remove and return an arbitrary key-value pair from the dictionary. If the dictionary is empty, calling popitem () raises an KeyError exception.

>>> a={'Gender':'Female','Age':7,'Hair color':None,'Name':'Zara'} >>> a.popitem() ('Gender', 'Female') >>> a.popitem() ('Age', 7) >>> a {'Hair color': None, 'Name': 'Zara'}

diet.setdefault(key[,default])

If key is in the dictionary, return its value. If not, insert key with a value of default and return default. The default defaults to None.

>>> a={'Name':'Zara','Age':7} >>> a.setdefault('Age',15) 7 >>> a.setdefault('Gender','Female') 'Female' >>> a.setdefault('Hair color') >>> a {'Gender': 'Female', 'Age': 7, 'Hair color': None, 'Name': 'Zara'}

dict.update([other])

Update the dictionary with the key-value pairs from other, overwriting existing keys, and returns None. The method accepts either another dictionary object or an iterable of key-value pairs (as tuples or other iterables of length two). If keyword arguments are specified, the dictionary is then updated with those key-value pairs.

>>> diet1={'Name':'Zara','Age':7} >>> dict2={'Gender':'female'} >>> diet1.update(dict2) >>> dictl.update(hair_color='black',eye_color='blue') >>> dictl {'eye_color': 'blue', 'Gender': 'female', 'Age': 7, 'Name': 'Zara', 'hair color': 'black'}

dict.values()

Return list of dictionary values.

>>> a={'Name':'Zara','Age':7} >>> a.values() [7, 'Zara']