0% found this document useful (0 votes)
12 views

Unit - 2 Sequence Data Types and OOP

Uploaded by

Mohan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Unit - 2 Sequence Data Types and OOP

Uploaded by

Mohan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 84

Unit - II

Sequences, Mappings and Sets


Several sequential data structures have been introduced in this book, including strings, tuples, lists, and
structures that can be implemented using lists, such as stacks, queues and priority queues. This chapter further
gives a set of commonly used methods for sequential types, before moving on to two typical container data
structures that are not sequential: dicts and sets. While dicts represent unordered mappings from keys to values,
a set represents an unordered container of immutable objects. Both dicts and sets are mutable. This chapter
finishes by introducing a set of bitwise operators, which enable the implementation of sets using non-negative
integers.
8.1 Methods of Sequential Types
The previous chapter has introduced a set of methods for list modification. In addition to these
methods, there is another set of methods that return information about a list object without modifying
it. List information methods typically apply to immutable sequential objects, such as strings and
tuples, also. This section introduces common methods for sequential types, and in particular for
strings, by categorizing them according to the functionality. One commonly-used method is index,
which takes one argument and returns the index of the first occurrence of the argument in the
sequence. If the argument is not in the sequence, a value error is reported.
>>> l = [1, 2, 3]
>>> l.index(2)
1
>>> l.index(4)
Traceback ( most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 4 is not in list
>>> t = (1.0, 2.5, 3.3, 2.5)
>>> t.index(2.5)
>>> t.index(3.0)
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
ValueError: tuple.index(x): x not in tuple
>>> s = "abcdefgfedcba"
>>> s.index(‘c’)
2
>>> s.index(‘cba ’)
10
>>> s.index(‘h’)
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
ValueError: substring not found
As shown in the example above, the index method for strings can also take a string
argument that consists of more than one characters, returning the index of the first character in
the string if the argument is a sub string.
Another useful sequence information method is count, which takes one
argument and returns the number of occurrences of the argument in the sequence. If the
argument does not occur in the sequence, 0 is returned.
>>> t = (‘2’, ‘3’, ‘5’, ‘7’, ‘3’, ‘5’, ‘6’, ‘3’, ‘2’)
>>> t.count(‘3’)
3
>>> t.count(3)
0
>>> t.count(‘1’)
0
>>> s = ‘exciting’
>>> s.count(‘i’)
2
>>> s.count(‘it’)
1
As shown by the example above, the string method count can also take a string argument that
consists of more than one characters. As a sequence type for I/O, the string type has a number of
useful methods that the tuple and list types do not have. String methods can be classified into
two basic categories. The first category returns information about a string, and the second
category formats a string. Because string objects are immutable, string formatting methods
return a copy of the string object, rather than modifying the object in place. A set of commonly-
used string information methods include:
• isupper(), which takes no arguments and returns True if there is at least one cased character in
the string and all cased characters in the string are in upper case, and False otherwise;
• islower(), which takes no arguments and returns True if there is at least one cased character in
the string and all cased characters in the string are in lower case, and False otherwise;
• isalpha(), which takes no arguments, and returns True if the string is non-empty and all the
characters in the string are alphabetic, and False otherwise;
• isdigit(), which takes no arguments, and returns True if the string is non-empty and all the
characters in the string are digits, and False otherwise;
• isspace(), which takes non arguments, and returns True if the string is non-empty and all the
characters in the string are whitespaces (e.g. spaces, tabs and new lines), and False otherwise.
>>> s1 = ‘abcdef’
>>> s2 = ‘A1’
>>> s3 = ‘ABC’
>>> s4 = ‘__name__’
>>> s5 = ‘hello!’
>>> s6 = ‘name@institute’
>>> s7 = ‘12345’
>>> s8 = ‘123 456’
>>> s9 = ‘’
>>> s10 = ‘’
>>> s1.isupper()
False
>>> s2.isupper()
True
>>> s3.isupper()
True
>>> s8.isupper()
False
>>> s9.isupper()
False
>>> s10.isupper()
False
>>> s1.islower()
True
>>> s4.islower()
True
>>> s5.islower()
True
>>> s1.isalpha()
True
>>> s2.isalpha()
False
>>> s7.isalpha()
False
>>> s8.isalpha()
False
>>> s10.isalpha()
False
>>> s1.isdigit()
False
>>> s4.isdigit()
False
>>> s6.isdigit()
False
>>> s7.isdigit()
True
>>> s8.isdigit()
False
>>> s9.isdigit()
False
>>> s8.isspace()
False
>>> s9.isspace()
True
>>> s10.isspace()
False
A set of string information methods that search for a sub string includes:
• rindex(s), which takes a string argument s and returns the last occurrence of the argument in the
string. If the string argument contains more than one characters, the index of the first character is
returned. If the string argument is not a sub string of the string, a value error is reported. rindex is the
counterpart of index for string objects, returning the first occurrence of the sub string from the right,
rather than from the left.
• find(s), which takes a string argument s and returns the first occurrence of the argument in the string.
If the string argument contains more than one characters, the index of the first character is returned. If
the string argument is not a sub string of the string, find returns –1. find can be treated as an alternative
to index for string objects, with the difference being the responce when the string argument is not a
sub string: while the former returns –1, the latter raises a value error.
• rfind(s), which takes a string argument s and returns the last occurrence of the argument in the string.
If the string argument contains more than one characters, the index of the first character is returned. If
the string argument is not a sub string of the string, rfind returns –1. rfind is the counterpart of find,
returning the first occurrence of the string argument from the right, rather than from the left.
>>> s = ‘abcdefdefabc ’
>>> s.index(‘abc ’)
0
>>> s.find(‘def ’)
3
>>> s.rfind(‘de ’)
6
>>> s.rindex(‘a’)
9
>>> s.index(‘abd ’)
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
ValueError: substring not found
>>> s.rfind(‘abd ’)
-1
The index,rindex, find and rfindmethods can take optional arguments that specify a slice of the string
in which the sub string is looked for. This is achieved by two optional arguments, indicating the start
index and the end index of the slice, respectively. The locations of the slicing indices are the same as
those by the getslice operations. In case only the start index is specified, the slice ends at the end of the
string
>>> s = ‘abcabcabcdefdefabc’
>>> s.index(‘abc’, 3) # search s[3:]
3
>>> s.find(‘abc’, 5, -2) # search s[5:-2]
6
A set of convenient methods for checking the beginning and end of a string include:
• startswith(s), which takes a string argument s and returns True if the string starts with the argument,
and False otherwise;
• endswith(s), which takes a string argument s and returns True if the string ends with the argument,
and False otherwise.
>>> s = ‘abcdefghi’
>>> s.startswith(‘a’)
True
>>> s.startswith(‘abc’)
True
>>> s.endswith(‘d’)
False
>>> s.endswith(‘hi’)
True
The methods startswith and endswith can also take a tuple of strings as the argument, in which
case the return value is True if the string starts with any string in the tuple, and False otherwise.
>>> s = ‘abcdefghi ’
>>> s.startswith((‘abc ’, ‘def ’))
True
>>> s.startswith((‘a’, ‘b’, ‘c’))
True
>>> s.endswith((‘def ’, ‘abc ’))
False
>>> s.endswith((‘ghi ’, ‘hi ’, ‘i’))
True
A set of string formatting methods that modify the cases of cased characters includes:
• upper(), which takes no arguments and returns a copy of the string object with all cased
characters converted to the upper case;
• lower(), which takes no arguments and returns a copy of the string object with all cased
characters converted to the lower case;
• swapcase(), which takes no arguments and returns a copy of the string object with all upper-
case characters converted into the lower case, and vice versa.
>>> s = ‘Abc!’
>>> s.upper()
‘ABC!’
>>> s.lower()
‘abc!’
>>> s.swapcase()
‘aBC!’
A set of string formatting methods that adds or removes whitespaces on the ends of a string
includes:
• ljust(x), which takes an input argument s that specifies a length, and returns a copy of the
string left justified in a string of the specified length. Spaces are padded on the right if the length
is longer than the length of the string, while no truncation is performed if the length is smaller
than the length of the string.
• rjust(x), which takes an input argument s that specifies a length, and returns a copy of the
string right justified in a string of the specified length. Spaces are padded on the left if the length
is larger than the length of the string, while no truncation is performed if the length is smaller
than the length of the string.
• lstrip(), which takes no arguments and returns a copy of the string with whitespaces on the left
being stripped.
• rstrip(), which takes no arguments and returns a copy of the string with whitespaces on the
right being stripped.
• strip(), which takes no argument and returns a copy of the string with whitespaces on both
sides being stripped.
>>> s = ‘abc’
>>> s.ljust(5)
‘abc ’
>>> s.rjust(6)
‘ abc’
>>> s.ljust(2)
‘abc’
>>> s = ‘ abc\n\t’
>>> s
‘ abc\n\t’
>>> s.lstrip()
‘abc\n\t’
>>> s.rstrip()
‘abc’
>>> s.strip()
‘abc’

The methods above can be generalized to insert or strip arbitrary characters on the
ends of a string. In particular, ljust and rjust can take an additional argument that specifies a
padding character, while lstrip, rstrip and strip can take an additional argument that specifies a
set of characters to be stripped.
>>> s = ‘123’
>>> s.ljust(5, ‘0’) # pad ‘0’
‘12300’
>>> s.rjust(6, ‘-’) # pad ‘-’
‘---123’
>>> s = ‘aabcdceft’
>>> s.lstrip(‘a’) # strip ‘a’
‘bcdceft’
>>> s.lstrip(‘bac’) # the set {‘b’, ‘a’, ‘c ’}
‘dceft’
>>> s.rstrip(‘ag’) # the set {‘a’, ‘g ’}
‘aabcdceft’
>>> s.strip(‘gabf’) # {‘g’, ‘a’, ‘b’, ‘f ’}
‘cdceft’
A method that splits a string into a list of sub strings is split, which takes a single argument
specifying the deliminator, and returns the list that results from the splitting.
>> s = ‘1 2 3’
>>> s.split(‘’)
[‘1’, ‘2’, ‘3’]
>>> s = ‘1<2<3’
>>> s.split(‘<’)
[‘1’, ‘2’, ‘3’]
>>> s = ‘1==2==3’
>>> s.split(‘=’)
[‘1’, ‘’, ‘2’, ‘’, ‘3’]
>>> s.split(‘==’)
[‘1’, ‘2’, ‘3’]
>>> s = ‘1!=2!=3’
>>> s.split(‘!=’)
[‘1’, ‘2’, ‘3’]
As shown by the example above, an empty string results in the splitting of two
consecutive deliminators, and a deliminator can be an arbitrary string that contains one or more
characters.
The input deliminator is optional; when it is not specified, all consecutive runs of whitespace
characters are taken as deliminators
>>> s = ‘ 1 2\t\t3\n4’
>>> s
‘ 1 2\t\t3\n4’
>>> s.split()
[‘1’, ‘2’, ‘3’, ‘4’]
The reverse method to split is join, which takes a list argument and joins the list into a string
with the string being the concatenator.
>>> s = ‘’
>>> s.join([‘1’, ‘2’, ‘3’])
‘1 2 3’
>>> l = [‘abc’, ‘d’, ‘ef’]
>>> ‘--’.join(l)
‘abc --d--ef’
>>> ‘-’.join([1, 2, 3])
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
TypeError: sequence item 0: expected string , int found
As shown by the examples above, the split method returns a list of strings, and a list of
strings should be used as the argument to join. Any other list items are not allowed by the join
method, and no implicit conversion is performed.
Using split and join, one can replace all occurrences of a sub string in a string with another
string. For example, the following code replaces all occurrences of ‘abc’ in a string into ‘—’:
>>> s1 = ‘abc’
>>> s2 = ‘---’
>>> s = ‘abcdefabcghiabc’
>>> s2.join(s.split(s1))
‘---def ---ghi ---’
Python provides a method, repalce, for sub string replacement directly. It takes two string
arguments, specifying the substring to be replaced and the replacement string, respectively, and
returns a copy of the string after replacement.
>>> s = ‘abcdefabcghiabc’
>>> s.replace(‘abc’, ‘---’)
‘---def ---ghi ---’
replace allows an additional argument that specifies a count, so that the first occurrences of the sub
string up to the count are replaced.
>>> s = ‘abcdefabcghiabc ’
>>> s.replace(‘abc ’, ‘---’, 1)
‘---defabcghiabc ’
>>> s.replace(‘abc ’, ‘---’, 2)
‘---def ---ghiabc ’
A final string formatting method is format, which is an alternative to the string formatting
expression introduced in Chap. 3. The method is bound to a pattern string, and takes arguments
that fill pattern fields in the string. A pattern field is formed by a pair of curly brackets, and
contains either a number specifying the index of the corresponding argument, or a keyword to be
filled by a keyword argument. For example,
>>> ‘{0} + {1} = {2}’. format(1, 2, 1+2)
‘1 + 2 = 3’
>>> ‘Hello , {0}’. format(‘Python ’)
‘Hello , Python ’
>>> ‘{2}-{0}-{1}’. format(‘abc ’, ‘def ’, ‘ghi ’)
‘ghi -abc -def ’
>>> ‘{x}-{y}-{0}’. format(‘ghi ’, x=‘abc ’, y=‘def ’)
‘abc -def -ghi ’
In the example above, the last method call contains two keyword arguments, x and y, which fill
the keyword fields {x} and {y}, respectively. Note that similar to other function calls, keyword
arguments must be placed after non-keyword arguments. If the arguments are sequentially filled,
the indics in the pattern fields can be omitted.
>>> ‘{} + {} = {}’.format(1, 2, 3)
‘1 + 2 = 3’

Formatting specifications can be given to each pattern field by using ‘:’, where follows the
pattern syntax in string formatting expressions. For example,
>>> ‘{0:d} + {1:.2f} = {2}’.format(1, 2.0, 1+2.0)
‘1 + 2.00 = 3.0’
>>> s = ‘{0:d} + {1:.2f} = {x:s}’
>>> s.format(1, 2, x=str(1+2))
‘1 + 2.00 = 3’
In the example above, ‘:d’, ‘:.2f’ and ‘:s’ are used to specify the format of an integer, a
floating point number with 2 digits after the decimal point and a string, respectively. Formatting
specifications can be used for keyword and non-keyword arguments.
If there are too few arguments, an error will be raised. If there are too many arguments, the
first ones will be used to fill the pattern string
>>> s=‘{} + {} = {}’
>>> s.format(1)
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
IndexError: tuple index out of range
>>> s.format(1, 2, 3, 4)
‘1 + 2 = 3’
There is a built-in function, format(v,s), which takes a value v and a pattern string s as its input
arguments, and return a string by calling s.format(v).
>>> format (3.1,‘.2f’) ‘3.10’
The methods and functions above are frequently used for sequential types, and this section
categories them according to the functionality and return type. There are more methods for
sequential types. The Python documentation is a useful reference for looking for a pre-defined
function before writing one custom function.
8.2 Dicts—A Mutable Mapping Type
The dict type is a container type. Similar to lists, dict objects are mutable. On the other hand,
unlike lists and tuples, which are sequential containers, dicts are associative containers, which
represent mappings from keys to values. Intuitively, dict objects resemble dictionaries, which
map words to their meanings. When a word is looked up in a dictionary, it is used as a key for
finding the corresponding value, which is the entry explaining the word. Dicts generalize the
definitions of keys and values, and are useful for mapping student IDs to their GPAs, looking up
the price of a stock given a company name, and other key-value associations where keys are
discontinuous and distinct.
Formally, a dict object consists of a set of (key, value) pairs, which are items. A
key must be an immutable object, while a value can be any object. The most important
operation for a dict object is lookup, which returns the corresponding value given a key. As a
result, keys must be distinct in a dict object, but values do not have to be distinct.
A dict literal consists of a comma-separated list of key: value pairs, enclosed in a pair of curly
brackets.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d
{1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> type(d)
<type ‘dict’>
>>> d = {1.0: 1, True: 1+2j, None: ‘abc’, (1,2): False}
>>> d
{(1, 2): False , 1.0: (1+2j), None: ‘abc’}
>>> type(d)
<type ‘dict’>
>>> d = {[1,2]: ‘a’}
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
TypeError: unhashable type: ‘list’
In the example above, the first dict represents a mapping from integers to strings. The second
dict represents a mapping between miscellaneous objects, where the keys include the floating
point number 1.0, the Boolean object True, the None object and the tuple object (1, 2), and the
values include the integer 1, the complex number 1 + 2j, the string ‘abc’ and the Boolean object
False. The third dict literal leads to an error, because the mutable object [1, 2] is used as a key.
The literal of an empty dict is {}.
When two duplicated keys are defined in a dict literal, the latter overrides the former.
>>> d = {‘a’: 1, ‘b’: 2, ‘a’: 3}
>>> d
{‘a’: 3, ‘b’: 2}
In the example above, d contains two identical keys, which are mapped into the integers 1 and 3,
respectively. Python discards the key value pair (‘a’, 1), keeping only (‘a’, 3) for the key ‘a’.
Python uses the == operator to decide whether two keys are identical. As a result, two numerical
values can be identical even if their types are different.
>>> d = {1: ‘a’, 2: ‘b’, 1.0: ‘c’}
>>> d
{1: ‘c’, 2: ‘b’}
In the example above, the keys 1 and 1.0 are treated as identical because the
expression 1 == 1.0 is True. As immutable objects, floating point numbers can be used as keys to
dicts. However, due to rounding off errors, Python’s representation of floating point numbers
can be imprecise. These can also be conflit with integer keys as shown above. As a result, it is
recommended to avoid the use of floating point numbers as keys when possible.
Dict operators similar to tuples and lists, the == and != operators can be used to find the equality
between dict objects. Dicts are unordered collections, the order in which items are specified or
added to a dict object does not affect the value of the dict object.
>>> d1 = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d2 = {3: ‘c’, 1: ‘a’, 2: ‘b’}
>>> d3 = {}
>>> d1 == d2
True
>>> d1 != d3
True
The lookup operation is the most commonly used operation for dict objects. The syntax is
formally identical to that of the getitem operation for tuples and lists, which specify the index of
an item by a pair of square brackets. The only difference is that for a dict object, a key is used in
the place of the index for tuples and lists.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d[1]
‘a’
>>> d[3]
‘c’
>>> d[5]
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
KeyError: 5
As shown by the example above, a key error is raised if the key to lookup is not in the dict object.
The dict method get is commonly used as an alternative to lookup, which allows default values if
the specified key is not in the dict:
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d.get(3, ‘z’)
‘c’
>>> d.get(5, ‘z’)
‘z’
As shown in the example above, get takes two arguments, the first being the key, and the second
being the default value. If the key is in the dict, the return value is thevalue of the key in the dict.
Otherwise the default value is returned by get.
Similar to the case of tuples and lists, the operator in and not in can be applied to a dict object,
returning whether an object is in the dict or not. When applied to a dict, the operators return
whether an object is a key in the dict.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> 1 in d
True
>>> 4 in d
False
>>> ‘a’ in d
False
Note that the last expression in the example above is evaluated to False, because ‘a’ is not a key
in d, despite that it is the value of the key 1 in d.
The method call d.get(k, v) can be regarded as a succinct version of the following function:
def defaultlookup (d, k, v):
if k in d:
return d[k]
else :
return v
The len function can be applied to dict objects, returning the number of items in the dict.
>>> len({1: ‘a’, 2: ‘b’, 3: ‘c’})
3
>>> len({})
0
Conversion between dicts and other types. Dicts can be converted to strings, Boolean objects,
tuples and lists, but not to numbers. The string conversion of a dict object represents the literal
form of the dict object.
>>> a = 1.0
>>> b = True
>>> c = ‘a’
>>> d = {a: 1, 2: b, c: 3}
>>> str(d)
"{‘a’: 3, 1.0: 1, 2: True}"
The Boolean conversion of a dict is False only when the dict is empty, and True otherwise.
>>> bool({1: ‘a’, 2: ‘b’, 3: ‘c’})
True
>>> bool({1: 1})
True
>>> bool({})
False
The tuple and list conversions of a dict object consist of all the keys in the dict object.
>>> d = {1: 1.0, 2: 9, 3: 8}
>>> tuple(d)
(1, 2, 3)
>>> list(d)
[1, 2, 3]
Lists and tuples can be converted to dicts using the dict function, but numbers, strings, or
Boolean objects cannot. To be convertable to a dict, a tuple or list must be a sequence (key,
value) pairs.
>>> d1 = dict(((3, ‘a’), (2, ‘b’), (3, ‘c’)))
>>> d2 = dict([(3, ‘a’), (2, ‘b’), (3, ‘c’)])
>>> d1
{2: ‘b’, 3: ‘c’}
>>> d1 == d2
True
8.2.1 Dict Modification
There are two ways to change a dict object. The first is the setitem operation, which sets the
value of a key directly via the assignment syntax, and the delitem operator, which deletes a key-
value pair from a dict object. The syntax of the setitem operation is d[key] = value, where d is a
dict identifier, key is an immutable object and value is an arbitrary object. If key is not an
existing key in d, (key, value) is added as a new item in d. Otherwise, value is used to replace the
old value of key in d. For example
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d[0] = ‘’ # adds a new entry to d
>>> d
{0: ‘’, 1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d[1] = ‘e’ # update an existing entry in d
>>> d
{0: ‘’, 1: ‘e’, 2: ‘b’, 3: ‘c’}
The syntax of the delitem operation is
del d[key]
where d is a dict identifier and key is an immutable object. If key is an existing key in d, the
corresponding item will be removed from d. Otherwise a key error is raised. A commonly used
method to change a dict object is update, which takes a single dict argument, using it to update
the dict. In particular, each (key, value) pair in the argument is enumerated, and used to update
the dict in the same way as setitem. If key is not already in the dict, the item (key, value) is added
to the dict as a new item.
Otherwise, the corresponding value of key is updated by value. The return value of the update
method is None.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d1 = {0: ‘’, 1: ‘e’}
>>> d.update(d1)
>>> d
{0: ‘’, 1: ‘e’, 2: ‘b’, 3: ‘c’}
In the example above, d1 is used to update d. There are two items in d1, namely (0, ‘ ’) and (1,
‘e’). The key 0 is not in d before the update, and therefore (0, ‘ ’) is added to d. On the other
hand, the key 1 is already in d, and therefore the existing item (1, ‘a’) in d is updated with the
item (1, ‘e’).
A method to remove an item from a dict is pop, which takes a single argument. If the argument
is a key in the dict, the corresponding item is removed, with is value returned. Otherwise, a key
error is raised.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d.pop(1)
‘a’
>>> d
{2: ‘b’, 3: ‘c’}
>>> d.pop(0)
Traceback ( most recent call last):
File "<stdin >", line 1, in <module >
KeyError: 0
pop can take an optional second argument, which specifies the default return value if the first
argument is not a key in the dict. When the second argument is given, no key error is raised.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d.pop(1, ‘d’)
‘a’
>>> d
{2: ‘b’, 3: ‘c’}
>>> d.pop(0, ‘d’)
‘d’
>>> d
{2: ‘b’, 3: ‘c’}
A method that removes all the items from a dict object is clear, which takes no argument, and
returns None.
>>> d = {1: ‘c’, 2: ‘b’, 3: ‘c’}
>>> d.clear()
>>> d
{}
Similar to the case of lists, modifications to a dict object shared by multiple identifiers results in
a simultaneous change of values of all the identifiers.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d1 = d
>>> t1 = (d1 , 4, ‘d’)
>>> def f(d2):
... d2.update({0: ‘e’, 1: ‘d’})
... del d2[3]
...
>>> f(t1[0])
>>> d
{0: ‘e’, 1: ‘d’, 2: ‘b’}
>>> d1
{0: ‘e’, 1: ‘d’, 2: ‘b’}
>>> t1
({0: ‘e’, 1: ‘d’, 2: ‘b’}, 4, ‘d’)
In the example above, the identifiers d, d1 and t1[0] are bound to the same dict object. When f is
called, the local identifier d2 is bound to the same object as the argument. As a result, when f
(t1[0]) is called, all the identifiers above are changed.
In addition to dict modification methods, the dict type also supports a set of methods that return
information of a dict object, including keys, values and items, which take no argument and
return a list of copies of the keys, values and items of a dict object, respectively.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> d.keys()
[1, 2, 3]
>>> d.values()
[‘a’, ‘b’, ‘c’]
8.2 Dicts—A Mutable Mapping Type 201
>>> d.items()
[(1, ‘a’), (2, ‘b’), (3, ‘c’)]
Because the return values of the methods are copies of the original keys, values and items,
modifications to the return values do not affect the original dict.
>>> d = {1: ‘a’, 2: ‘b’, 3: ‘c’}
>>> l = d.keys()
>>> l
[1, 2, 3]
>>> l[0] = 0
>>> l
[0, 2, 3]
>>> d
{1: ‘a’, 2: ‘b’, 3: ‘c’}

8.3 Sets and Bitwise Operations


Another commonly-used container type is set, which represents an unordered container of
immutable objects. Similar to lists and dicts, sets are mutable. Compared with lists, sets have
two main differences. First, sets are unordered but lists are ordered.
Second, sets do not allow duplicated items, but the same item can exit in a list multiple times.
Sets are connected to dicts in that both set items and dict keys are distinct. A set can be
implemented as a special dict, with the keys representing the items in the set, and the values
being dummy values (e.g. 1), which are ignored.
A set literal consists of a comma-separated list of literals or identifiers, enclosed in a pair of
curly brackets.
>>> a = 1
>>> i = 5.6
>>> s = {a, True , i}
>>> s
set([5.6, True])
>>> type(s)
<type ‘set’>
The literal of an empty set is set() rather than {}, which represents an empty dict object. The set
function is similar to the functions int, float, complex, bool, str, tuple, list and dict in that it
constructs a new set object. Set operators. Sets support the in and not in operators, which return
whether an item is in a set or not. The builtin function len can be used to find the cardinality of a
set.
>>> s = {1, 2, 3}
>>> 1 in s
True
>>> 3 not in s
False
>>> 4 not in s
True
>>> len(s)
3
>>> len(set()) # empty set
0
The operators >, >=, < and <= are applied to two set objects, returning whether the first set is a
proper superset, a superset, a proper subset and a subset of the second set, respectively. The
methods issubset and issuperset achieve the same functionalities as the operators >= and <=,
respectively.
>>> a = {1, 2, 3}
>>> b = {3, 4, 5}
>>> c = {3}
>>> a >= c
True
>>> a > b
False
>>> b.issuperset(c)
True
>>> set().issubset(c)
True
>>> c < b
True
The following operators and methods are applied to two set objects, returning a new set object.
• The | operator and the union method return the union of the two sets;
• The & operator and the intersection method return the intersection of the two sets;
• The − operator and the difference method return the difference between the two

• The ∧ operator and the symmetric_difference method return the symmetric difference
sets, which contains all the items in the first set that are not in the second set.

between the two sets, which consists of elements in either but not both of the sets.
>>> s1 = {1, 2, 3}
>>> s2 = {3, 4}
>>> s1&s2
set([3])
>>> s1.union(s2)
set([1, 2, 3, 4])
>>> s1 -s2
set([1, 2])
>>> s1.symmetric_difference(s2)
set([1, 2, 4])
Conversion between sets and other types. Set objects can be converted into strings, Boolean
objects, tuples and lists. The string conversion of a set object is aliteral form of the set; the
Boolean conversion of a set object is False only if the set is empty, and True otherwise; the tuple
and list conversions of a set object consists of all the items in the set, in arbitrary (but not
random) order.
>>> s = {‘a’, ‘b’, ‘c’, 1, 2, 3}
>>> str(s)
"set([‘a’, 1, 2, 3, ‘c’, ‘b’])"
>>> print s
set([‘a’, 1, 2, 3, ‘c’, ‘b’])
>>> bool(s)
True
>>> if s :
... print ‘non -empty ’
...
non -empty
>>> tuple(s)
(‘a’, 1, 2, 3, ‘c’, ‘b’)
>>> list(s)
[‘a’, 1, 2, 3, ‘c’, ‘b’]
Strings, tuples, lists and dicts can be converted into sets. The set conversion of a string consists of
all the characters in the string, the set conversion of a tuple or a list consists of all the items in
the sequence, while the set conversion of a dict consists of all the keys.
>>> set("123")
set([‘1’, ‘3’, ‘2’])
>>> set([‘c’, True , 1+3j])
set([True , ‘c’, (1+3j)])
>>> set({1:1, 2:0, 3:-1})
set([1, 2, 3])

8.3.1 Set Modification


The set type supports a set of methods that modify a set object, which can be classified into set-
element methods and set-set methods. Commonly used set-element methods include:
• add(x), which takes an immutable argument x and adds the argument into the set;
• remove(x), which takes an immutable argument x and removes the argument from
the set. A key error is raised if the argument is not in the set;
• discard(x), which takes an immutable argument x and removes the argument from
the set. If the argument is not in the set, no action is taken.
• pop(), which takes no argument, and removes an arbitrary item from the set, returning its
value.
>>> s = {1, 2, 3}
>>> s.add(0)
>>> s
set([0, 1, 2, 3])
>>> s.remove(5)
KeyError: 5
>>> s.discard(3)
>>> s
set([0, 1, 2])
>>> s.pop()
0
>>> s
set([1, 2])
Commonly-used set-set methods include:
• update(s), which takes a set argument s, adding all the items in the argument s into
the set. The operator |= achieves the same functionality as this method.
• intersection_update(s), which takes a set argument s, and updates the set, keeping only those
items that are also in the argument s. The operator &= achieves the same functionality as this
method.
• difference_update(s), which takes a set argument s, and updates the set, removing
those items that are also in the argument s. The operator −= achieves the same functionality as
this method.
• symmetric_difference_update(s), which takes a set argument s, and updates the set, keeping
only items that are in either the set or the argument s, but not in both.
In the example above, the four set-set operations are applied to the sets
{1, 2, 3} and {3, 4}, respectively. Because they are set modification methods, a
copy of the original set is necessary for keeping the original sets. The set type provides a method,
copy, which takes no argument and returns a copy of the set. As a result, copy.copy(s1) in the
examples above can be replaced with s1.copy().
Similar to dicts, sets support the clear method, which takes no arguments and removes all the
items from the set. Set are iterable. The for loop can be used to iterate through a set object.
Because sets are unordered, their iteration takes an arbitrary (but not random) order.
>>> s = {1, ‘a’, 2, ‘b’, None , True}
>>> for i in s :
... print i
...
a
True
2
b
None

8.3.2 Bitsets and Bitwise Operators


Sets are inherently connected to binary numbers. As mentioned in Chap. 2, integers can be
written in binary forms, in which each digit is either 0 or 1. Intuitively, the values 0 and 1 can be
used to represent whether an item is in a set or not. As a result, if the possible elements in a set is
finite, they can be indexed and associated with a finite number of bits in a binary number. Each
possible set element corresponds with a specific bit in the number.
The correlation between a finite set and a binary number is shown in Fig. 8.1.
As can be seen from the figure, the value (i.e. 0 or 1) of the ith bit in the integer
corresponds to the presence of the ith possible item in the set. On the other hand, the ith bit in
the integer also represents the value of 2i As a result, the set {e1, e3, e7} corresponds to the
integer 21 + 23 + 27 = 2 + 8 + 128 = 138.
Python supports binary integer literals, which start from the letters ‘0b’, followed by binary
digits. For example, 0b1 represents 20 = 1, 0b10 represents 21 = 2, and between finite sets and
binary numbers
>>> 0b1101 # 2**3+2**2+2**0=13
13
>>> 0b1011 # 2**3+2**1+2**0=11
11
The bulitin function bin takes an integer argument and returns a string that shows the binary
form of the number.
>>> bin(13)
‘0b1101’
>>> bin(125)
‘0b1111101 ’
The connection between binary numbers and sets allows the use of integers to implement or
represent sets, provided that possible items in the set can be indexed. For example, the set{e1, e3,
e7}in Fig. 8.1 can be represented by the integer 0b10001010 = 27+23+21= 138. Given an integer,
its corresponding set can be examined by checking item presence in its binary representation.
The union, intersection and symmetric difference operations between two sets are connected to
digit-wise (or bitwise) Boolean operations between two binary numbers.
For example, in the union of the setss1 and s2, an item is present if the item is present in s1 or in
s2, while in the intersection of s1 and s2, an item is present if the item is present in s1 and in s2.
As a result, the binary numbers that correspond to the
union and intersection of s1 and s2 can be calculated from the binary numbers that correspond
to s1 and s2 by the bitwise or and bitwise and operations, respectively.
The binary number that corresponds to the symmetric difference between the two sets s1 and s2
can be calculated from the binary numbers that correspond to s1 and s2 by the bitwise xor
operation. The three bitwise operations are defined as follows.
In a bitwise or operation between two numbers n1 and n2, the ith bit of the result is 1 if the ith
bit of n1 is 1 or the ith bit of n2 is 1; in a bitwise and operation between two numbers n1 and n2,
the ith bit of the result is 1 if the ith bit of n1 is 1 and the ith bit of n2 is 1; in a bitwise xor
operation between two numbers n1 and n2, the ith bit of the result is 1 if the ith bit of n1 is

Python supports the bitwise operations above by the integer operation |, & and ∧, respectively.
different from the ith bit of n2, and 0 otherwise.

>>> a = 0b1101
>>> b = 0b1001
>>> a
13
>>> b
9
>>> a|b
13
>>> bin(a|b)
‘0b1101’
>>> a&b
8.3 Sets and Bitwise Operations 211
9
>>> bin(a&b)
‘0b1001’
>>> a^b
4
>>> bin(a^b)
‘0b100’
The correlation between set operations and bitwise integer operations is shown in
Fig. 8.2. Note that the difference (i.e. –) operation between two sets is not correlated to the –

|, & and ∧ are all binary bitwise operations, taking two operands. There is a unary bitwise
operation between two numbers, which is an arithmetic operator rather than a bitwise operator.

Boolean operator, ∼ , which takes one operand and flips every bit in it:
Fig. 8.2 The correlation between set operations and bitwise integer operations
>>> a=0b1010101100
>>> bin(~a)
‘-0b1010101101 ’
In addition to bitwise Boolean operations, Python also supports a set of bitwise shifting
operations between two integers. In particular, right-shift operation n >> k shifts the binary
form of n to the right by k bits, and the left-shift operation n >> k shifts the binary form of n to
the left by k bits. In terms of the value, the operation n >> k is equivalent to n/(2k ) and the n k
operation is equivalent to n × 2k . In both n/(2k ) and n × 2k , n is treated as a positive integer.
>>> n = 0b1011
>>> bin(n<<1)
0b10110
>>> bin(n>>1)
0b101

Python Classes and Objects





A class is a user-defined blueprint or prototype from which objects are
created. Classes provide a means of bundling data and functionality together.
Creating a new class creates a new type of object, allowing new instances of that
type to be made. Each class instance can have attributes attached to it for
maintaining its state. Class instances can also have methods (defined by their class)
for modifying their state.
To understand the need for creating a class and object in Python let’s consider an example,
let’s say you wanted to track the number of dogs that may have different attributes like
breed and age. If a list is used, the first element could be the dog’s breed while the second
element could represent its age. Let’s suppose there are 100 different dogs, then how would
you know which element is supposed to be which? What if you wanted to add other
properties to these dogs? This lacks organization and it’s the exact need for classes.
Syntax: Class Definition
class ClassName:
# Statement
Syntax: Object Definition
obj ClassName()
print(obj.atrr)
The class creates a user-defined data structure, which holds its own data members and
member functions, which can be accessed and used by creating an instance of that class. A
class is like a blueprint for an object.
Some points on Python class:
 Classes are created by keyword class.
 Attributes are the variables that belong to a class.
 Attributes are always public and can be accessed using the dot (.) operator. Eg.:
My class.Myattribute
Creating a Python Class
Here, the class keyword indicates that you are creating a class followed by the name of the
class (Dog in this case).

class Dog:
sound = "bark"
Object of Python Class
An Object is an instance of a Class. A class is like a blueprint while an instance is a copy
of the class with actual values. It’s not an idea anymore, it’s an actual dog, like a dog of
breed pug who’s seven years old. You can have many dogs to create many different
instances, but without the class as a guide, you would be lost, not knowing what
information is required.
An object consists of:
 State: It is represented by the attributes of an object. It also reflects the
properties of an object.
 Behavior: It is represented by the methods of an object. It also reflects the
response of an object to other objects.
 Identity: It gives a unique name to an object and enables one object to interact
with other objects.

Declaring Class Objects (Also called instantiating a class)


When an object of a class is created, the class is said to be instantiated. All the instances
share the attributes and the behavior of the class. But the values of those attributes, i.e. the
state are unique for each object. A single class may have any number of instances.
Example:
Example of Python Class and object
Creating an object in Python involves instantiating a class to create a new instance of that
class. This process is also referred to as object instantiation.
Python3
# Python3 program to
# demonstrate instantiating
# a class
class Dog:

# A simple class
# attribute
attr1 = "mammal"
attr2 = "dog"

# A sample method
def fun(self):
print("I'm a", self.attr1)
print("I'm a", self.attr2)

# Driver code
# Object instantiation
Rodger = Dog()

# Accessing class attributes


# and method through objects
print(Rodger.attr1)
Rodger.fun()
Output:
mammal
I'm a mammal
I'm a dog
In the above example, an object is created which is basically a dog named Rodger. This
class only has two class attributes that tell us that Rodger is a dog and a mammal.
Explanation :
In this example, we are creating a Dog class and we have created two class variables attr1
and attr2. We have created a method named fun() which returns the string “I’m a, {attr1}”
and I’m a, {attr2}. We have created an object of the Dog class and we are printing at
the attr1 of the object. Finally, we are calling the fun() function.
Self Parameter
When we call a method of this object as myobject.method(arg1, arg2), this is automatically
converted by Python into MyClass.method(myobject, arg1, arg2) – this is all the
special self is about.
Python3
class GFG:
def __init__(self, name, company):
self.name = name
self.company = company

def show(self):
print("Hello my name is " + self.name+" and I" +
" work in "+self.company+".")

obj = GFG("John", "GeeksForGeeks")


obj.show()
The Self Parameter does not call it to be Self, You can use any other name instead of it.
Here we change the self to the word someone and the output will be the same.
Python3
class GFG:
def __init__(somename, name, company):
somename.name = name
somename.company = company

def show(somename):
print("Hello my name is " + somename.name +
" and I work in "+somename.company+".")

obj = GFG("John", "GeeksForGeeks")


obj.show()
Output: Output for both of the codes will be the same.
Hello my name is John and I work in GeeksForGeeks.
Explanation:
In this example, we are creating a GFG class and we have created the name, and
company instance variables in the constructor. We have created a method
named say_hi() which returns the string “Hello my name is ” + {name} +” and I work in
“+{company}+”.”.We have created a person class object and we passing the name John
and Company GeeksForGeeks to the instance variable. Finally, we are calling
the show() of the class.
Pass Statement
The program’s execution is unaffected by the pass statement’s inaction. It merely permits
the program to skip past that section of the code without doing anything. It is frequently
employed when the syntactic constraints of Python demand a valid statement but no useful
code must be executed.
class MyClass:
pass
__init__() method
The __init__ method is similar to constructors in C++ and Java. Constructors are used to
initializing the object’s state. Like methods, a constructor also contains a collection of
statements(i.e. instructions) that are executed at the time of Object creation. It runs as soon
as an object of a class is instantiated. The method is useful to do any initialization you want
to do with your object.

# Sample class with init method


class Person:

# init method or constructor


def __init__(self, name):
self.name = name

# Sample Method
def say_hi(self):
print('Hello, my name is', self.name)

p = Person('Nikhil')
p.say_hi()
Output:
Hello, my name is Nikhil
Explanation:
In this example, we are creating a Person class and we have created a name instance
variable in the constructor. We have created a method named as say_hi() which returns the
string “Hello, my name is {name}”.We have created a person class object and we pass the
name Nikhil to the instance variable. Finally, we are calling the say_hi() of the class.
__str__() method
Python has a particular method called __str__(). that is used to define how a class object
should be represented as a string. It is often used to give an object a human-readable
textual representation, which is helpful for logging, debugging, or showing users object
information. When a class object is used to create a string using the built-in functions
print() and str(), the __str__() function is automatically used. You can alter how objects of
a class are represented in strings by defining the __str__() method.

class GFG:
def __init__(self, name, company):
self.name = name
self.company = company

def __str__(self):
return f"My name is {self.name} and I work in {self.company}."
my_obj = GFG("John", "GeeksForGeeks")
print(my_obj)
Output:
My name is John and I work in GeeksForGeeks.
Explanation:
In this example, We are creating a class named GFG.In the class, we are creating two
instance variables name and company. In the __str__() method we are returning
the name instance variable and company instance variable. Finally, we are creating the
object of GFG class and we are calling the __str__() method.
Class and Instance Variables
Instance variables are for data, unique to each instance and class variables are for attributes
and methods shared by all instances of the class. Instance variables are variables whose
value is assigned inside a constructor or method with self whereas class variables are
variables whose value is assigned in the class.
Defining instance variables using a constructor.
# Python3 program to show that the variables with a value
# assigned in the class declaration, are class variables and
# variables inside methods and constructors are instance
# variables.

# Class for Dog

class Dog:

# Class Variable
animal = 'dog'

# The init method or constructor


def __init__(self, breed, color):

# Instance Variable
self.breed = breed
self.color = color

# Objects of Dog class


Rodger = Dog("Pug", "brown")
Buzo = Dog("Bulldog", "black")

print('Rodger details:')
print('Rodger is a', Rodger.animal)
print('Breed: ', Rodger.breed)
print('Color: ', Rodger.color)

print('\nBuzo details:')
print('Buzo is a', Buzo.animal)
print('Breed: ', Buzo.breed)
print('Color: ', Buzo.color)
# Class variables can be accessed using class
# name also
print("\nAccessing class variable using class name")
print(Dog.animal)
Output:
Rodger details:
Rodger is a dog
Breed: Pug
Color: brown
Buzo details:
Buzo is a dog
Breed: Bulldog
Color: black
Accessing class variable using class name
dog
Explanation:
A class named Dog is defined with a class variable animal set to the string “dog”. Class
variables are shared by all objects of a class and can be accessed using the class name. Dog
class has two instance variables breed and color. Later we are creating two objects of
the Dog class and we are printing the value of both objects with a class variable named
animal.
Defining instance variables using the normal method:

# Python3 program to show that we can create


# instance variables inside methods

# Class for Dog

class Dog:

# Class Variable
animal = 'dog'

# The init method or constructor


def __init__(self, breed):

# Instance Variable
self.breed = breed

# Adds an instance variable


def setColor(self, color):
self.color = color

# Retrieves instance variable


def getColor(self):
return self.color
# Driver Code
Rodger = Dog("pug")
Rodger.setColor("brown")
print(Rodger.getColor())
Output:
brown
Explanation:
In this example, We have defined a class named Dog and we have created a class
variable animal. We have created an instance variable breed in the constructor. The class
Dog consists of two methods setColor and getColor, they are used for creating and
initializing an instance variable and retrieving the value of the instance variable. We have
made an object of the Dog class and we have set the instance variable value to brown and
we are printing the value in the terminal.
Constructors in Python



Prerequisites: Object-Oriented Programming in Python, Object-Oriented Programming in
Python | Set 2
Constructors are generally used for instantiating an object. The task of constructors is to
initialize(assign values) to the data members of the class when an object of the class is
created. In Python the __init__() method is called the constructor and is always called
when an object is created.
Syntax of constructor declaration :
def __init__(self):
# body of the constructor
Types of constructors :
 default constructor: The default constructor is a simple constructor which
doesn’t accept any arguments. Its definition has only one argument which is a
reference to the instance being constructed.
 parameterized constructor: constructor with parameters is known as
parameterized constructor. The parameterized constructor takes its first
argument as a reference to the instance being constructed known as self and the
rest of the arguments are provided by the programmer.
Example of default constructor :
 Python3
class GeekforGeeks:

# default constructor
def __init__(self):
self.geek = "GeekforGeeks"

# a method for printing data members


def print_Geek(self):
print(self.geek)

# creating object of the class


obj = GeekforGeeks()

# calling the instance method using the object obj


obj.print_Geek()

Output
GeekforGeeks
Example of the parameterized constructor :
 Python3
class Addition:
first = 0
second = 0
answer = 0

# parameterized constructor
def __init__(self, f, s):
self.first = f
self.second = s

def display(self):
print("First number = " + str(self.first))
print("Second number = " + str(self.second))
print("Addition of two numbers = " + str(self.answer))

def calculate(self):
self.answer = self.first + self.second

# creating object of the class


# this will invoke parameterized constructor
obj1 = Addition(1000, 2000)

# creating second object of same class


obj2 = Addition(10, 20)

# perform Addition on obj1


obj1.calculate()

# perform Addition on obj2


obj2.calculate()
# display result of obj1
obj1.display()

# display result of obj2


obj2.display()

Output
First number = 1000
Second number = 2000
Addition of two numbers = 3000
First number = 10
Second number = 20
Addition of two numbers = 30

Example:
 Python
class MyClass:
def __init__(self, name=None):
if name is None:
print("Default constructor called")
else:
self.name = name
print("Parameterized constructor called with name", self.name)

def method(self):
if hasattr(self, 'name'):
print("Method called with name", self.name)
else:
print("Method called without a name")

# Create an object of the class using the default constructor


obj1 = MyClass()

# Call a method of the class


obj1.method()

# Create an object of the class using the parameterized constructor


obj2 = MyClass("John")

# Call a method of the class


obj2.method()

Output
Default constructor called
Method called without a name
('Parameterized constructor called with name', 'John')
('Method called with name', 'John')

Explanation:
In this example, we define a class MyClass with both a default constructor and a
parameterized constructor. The default constructor checks whether a parameter has been
passed in or not, and prints a message to the console accordingly. The parameterized
constructor takes in a single parameter name and sets the name attribute of the object to the
value of that parameter.
We also define a method method() that checks whether the object has a name attribute or
not, and prints a message to the console accordingly.
We create two objects of the class MyClass using both types of constructors. First, we
create an object using the default constructor, which prints the message “Default
constructor called” to the console. We then call the method() method on this object, which
prints the message “Method called without a name” to the console.
Next, we create an object using the parameterized constructor, passing in the name “John”.
The constructor is called automatically, and the message “Parameterized constructor called
with name John” is printed to the console. We then call the method() method on this object,
which prints the message “Method called with name John” to the console.
Overall, this example shows how both types of constructors can be implemented in a single
class in Python.

Advantages of using constructors in Python:


 Initialization of objects: Constructors are used to initialize the objects of a
class. They allow you to set default values for attributes or properties, and also
allow you to initialize the object with custom data.
 Easy to implement: Constructors are easy to implement in Python, and can be
defined using the __init__() method.
 Better readability: Constructors improve the readability of the code by making it
clear what values are being initialized and how they are being initialized.
 Encapsulation: Constructors can be used to enforce encapsulation, by ensuring
that the object’s attributes are initialized correctly and in a controlled manner.

Disadvantages of using constructors in Python:


 Overloading not supported: Unlike other object-oriented languages, Python
does not support method overloading. This means that you cannot have multiple
constructors with different parameters in a single class.
 Limited functionality: Constructors in Python are limited in their functionality
compared to constructors in other programming languages. For example,
Python does not have constructors with access modifiers like public, private or
protected.
 Constructors may be unnecessary: In some cases, constructors may not be
necessary, as the default values of attributes may be sufficient. In these cases,
using a constructor may add unnecessary complexity to the code.
Overall, constructors in Python can be useful for initializing objects and enforcing
encapsulation. However, they may not always be necessary and are limited in their
functionality compared to constructors in other programming languages.

Inheritance in Python



One of the core concepts in object-oriented programming (OOP) languages is inheritance.
It is a mechanism that allows you to create a hierarchy of classes that share a set of
properties and methods by deriving a class from another class. Inheritance is the capability
of one class to derive or inherit the properties from another class.
Benefits of inheritance are:
Inheritance allows you to inherit the properties of a class, i.e., base class to another, i.e.,
derived class. The benefits of Inheritance in Python are as follows:
 It represents real-world relationships well.
 It provides the reusability of a code. We don’t have to write the same code again
and again. Also, it allows us to add more features to a class without modifying it.
 It is transitive in nature, which means that if class B inherits from another class
A, then all the subclasses of B would automatically inherit from class A.
 Inheritance offers a simple, understandable model structure.
 Less development and maintenance expenses result from an inheritance.
Python Inheritance Syntax
The syntax of simple inheritance in Python is as follows:
Class BaseClass:
{Body}
Class DerivedClass(BaseClass):
{Body}

Creating a Parent Class


A parent class is a class whose properties are inherited by the child class. Let’s create a
parent class called Person which has a Display method to display the person’s
information.
# A Python program to demonstrate inheritance
class Person(object):

# Constructor
def __init__(self, name, id):
self.name = name
self.id = id

# To check if this person is an employee


def Display(self):
print(self.name, self.id)
# Driver code
emp = Person("Satyam", 102) # An Object of Person
emp.Display()

Output:
Satyam 102

Creating a Child Class


A child class is a class that drives the properties from its parent class. Here Emp is another
class that is going to inherit the properties of the Person class(base class).
class Emp(Person):

def Print(self):
print("Emp class called")

Emp_details = Emp("Mayank", 103)

# calling parent class function


Emp_details.Display()

# Calling child class function


Emp_details.Print()

Output:
Mayank 103
Emp class called
Example of Inheritance in Python
Let us see an example of simple Python inheritance in which a child class is inheriting the
properties of its parent class. In this example, ‘Person’ is the parent class, and ‘Employee’
is its child class.
# A Python program to demonstrate inheritance

# Base or Super class. Note object in bracket.


# (Generally, object is made ancestor of all classes)
# In Python 3.x "class Person" is
# equivalent to "class Person(object)"

class Person(object):

# Constructor
def __init__(self, name):
self.name = name
# To get name
def getName(self):
return self.name

# To check if this person is an employee


def isEmployee(self):
return False

# Inherited or Subclass (Note Person in bracket)


class Employee(Person):

# Here we return true


def isEmployee(self):
return True

# Driver code
emp = Person("Geek1") # An Object of Person
print(emp.getName(), emp.isEmployee())

emp = Employee("Geek2") # An Object of Employee


print(emp.getName(), emp.isEmployee())

Output:
Geek1 False
Geek2 True

What is an object class in Python?


Like the Java Object class, in Python (from version 3. x), the object is the root of all
classes.
 In Python 3.x, “class Test(object)” and “class Test” are same.
 In Python 2. x, “class Test(object)” creates a class with the object as a parent
(called a new-style class), and “class Test” creates an old-style class (without an
objecting parent).

Subclassing (Calling constructor of parent class)


A child class needs to identify which class is its parent class. This can be done by
mentioning the parent class name in the definition of the child class.
Example: class subclass_name (superclass_name)
In this example, ‘a’ is the instance created for the class Person. It invokes the __init__() of
the referred class. You can see ‘object’ written in the declaration of the class Person. In
Python, every class inherits from a built-in basic class called ‘object’. The constructor i.e.
the ‘__init__’ function of a class is invoked when we create an object variable or an
instance of the class.
The variables defined within __init__() are called instance variables or objects. Hence,
‘name’ and ‘idnumber’ are the objects of the class Person. Similarly, ‘salary’ and ‘post’ are
the objects of the class Employee. Since the class Employee inherits from class Person,
‘name’ and ‘idnumber’ are also the objects of class Employee.
# Python code to demonstrate how parent constructors
# are called.

# parent class
class Person(object):

# __init__ is known as the constructor


def __init__(self, name, idnumber):
self.name = name
self.idnumber = idnumber

def display(self):
print(self.name)
print(self.idnumber)

# child class
class Employee(Person):
def __init__(self, name, idnumber, salary, post):
self.salary = salary
self.post = post

# invoking the __init__ of the parent class


Person.__init__(self, name, idnumber)

# creation of an object variable or an instance


a = Employee('Rahul', 886012, 200000, "Intern")

# calling a function of the class Person using its instance


a.display()

Output:
Rahul
886012
Python program to demonstrate error if we forget to invoke __init__() of the parent
If you forget to invoke the __init__() of the parent class then its instance variables would
not be available to the child class. The following code produces an error for the same
reason.
class A:
def __init__(self, n='Rahul'):
self.name = n
class B(A):
def __init__(self, roll):
self.roll = roll

object = B(23)
print(object.name)

Output :
Traceback (most recent call last):
File "/home/de4570cca20263ac2c4149f435dba22c.py", line 12, in
print (object.name)
AttributeError: 'B' object has no attribute 'name'

The super() Function


The super() function is a built-in function that returns the objects that represent the parent
class. It allows to access the parent class’s methods and attributes in the child class.
Example: super() function with simple Python inheritance
In this example, we created the object ‘obj’ of the child class. When we called the
constructor of the child class ‘Student’, it initialized the data members to the values passed
during the object creation. Then using the super() function, we invoked the constructor of
the parent class.
# parent class
class Person():
def __init__(self, name, age):
self.name = name
self.age = age

def display(self):
print(self.name, self.age)

# child class
class Student(Person):
def __init__(self, name, age):
self.sName = name
self.sAge = age
# inheriting the properties of parent class
super().__init__("Rahul", age)

def displayInfo(self):
print(self.sName, self.sAge)

obj = Student("Mayank", 23)


obj.display()
obj.displayInfo()

Output:
Rahul 23
Mayank 23

Adding Properties
One of the features that inheritance provides is inheriting the properties of the parent class
as well as adding new properties of our own to the child class. Let us see this with an
example:
# parent class
class Person():
def __init__(self, name, age):
self.name = name
self.age = age

def display(self):
print(self.name, self.age)

# child class
class Student(Person):
def __init__(self, name, age, dob):
self.sName = name
self.sAge = age
self.dob = dob
# inheriting the properties of parent class
super().__init__("Rahul", age)

def displayInfo(self):
print(self.sName, self.sAge, self.dob)

obj = Student("Mayank", 23, "16-03-2000")


obj.display()
obj.displayInfo()

Output:
Here we can see that we added a new property to the child class, i.e., date of birth (dob).
Rahul 23
Mayank 23 16-03-2000

Different types of Python Inheritance


There are 5 different types of inheritance in Python. They are as follows:
 Single inheritance: When a child class inherits from only one parent class, it is
called single inheritance. We saw an example above.
 Multiple inheritances: When a child class inherits from multiple parent classes,
it is called multiple inheritances.
Unlike Java, python shows multiple inheritances.
# Python example to show the working of multiple
# inheritance

class Base1(object):
def __init__(self):
self.str1 = "Geek1"
print("Base1")

class Base2(object):
def __init__(self):
self.str2 = "Geek2"
print("Base2")

class Derived(Base1, Base2):


def __init__(self):

# Calling constructors of Base1


# and Base2 classes
Base1.__init__(self)
Base2.__init__(self)
print("Derived")

def printStrs(self):
print(self.str1, self.str2)

ob = Derived()
ob.printStrs()

Output:
Base1
Base2
Derived
Geek1 Geek2
 Multilevel inheritance: When we have a child and grandchild relationship. This
means that a child class will inherit from its parent class, which in turn is
inheriting from its parent class.
# A Python program to demonstrate inheritance

# Base or Super class. Note object in bracket.


# (Generally, object is made ancestor of all classes)
# In Python 3.x "class Person" is
# equivalent to "class Person(object)"
class Base(object):

# Constructor
def __init__(self, name):
self.name = name

# To get name
def getName(self):
return self.name

# Inherited or Sub class (Note Person in bracket)


class Child(Base):

# Constructor
def __init__(self, name, age):
Base.__init__(self, name)
self.age = age

# To get name
def getAge(self):
return self.age

# Inherited or Sub class (Note Person in bracket)

class GrandChild(Child):

# Constructor
def __init__(self, name, age, address):
Child.__init__(self, name, age)
self.address = address

# To get address
def getAddress(self):
return self.address

# Driver code
g = GrandChild("Geek1", 23, "Noida")
print(g.getName(), g.getAge(), g.getAddress())

Output:
Geek1 23 Noida
 Hierarchical inheritance More than one derived class can be created from a
single base.
 Hybrid inheritance: This form combines more than one form of inheritance.
Basically, it is a blend of more than one type of inheritance.
For more details please read this article: Types of inheritance in Python
Private members of the parent class
We don’t always want the instance variables of the parent class to be inherited by the child
class i.e. we can make some of the instance variables of the parent class private, which
won’t be available to the child class.
In Python inheritance, we can make an instance variable private by adding double
underscores before its name. For example:
# Python program to demonstrate private members
# of the parent class

class C(object):
def __init__(self):
self.c = 21

# d is private instance variable


self.__d = 42

class D(C):
def __init__(self):
self.e = 84
C.__init__(self)

object1 = D()

# produces an error as d is private instance variable


print(object1.c)
print(object1.__d)

Output :
Here we can see that when we tried to print the variable ‘c’, its value 21 is printed on the
console. Whereas when we tried to print ‘d’, it generated the error. This is because the
variable ‘d’ is made private by using the underscores. It is not available to the child class
‘D’ and hence the error.
21
File "/home/993bb61c3e76cda5bb67bd9ea05956a1.py", line 16, in
print (object1.d)
AttributeError: type object 'D' has no attribute 'd'

Class method vs Static method in Python





In this article, we will cover the basic difference between the class method vs Static
method in Python and when to use the class method and static method in python.
What is Class Method in Python?
The @classmethod decorator is a built-in function decorator that is an expression that gets
evaluated after your function is defined. The result of that evaluation shadows your
function definition. A class method receives the class as an implicit first argument, just like
an instance method receives the instance
Syntax Python Class Method:
class C(object):
@classmethod
def fun(cls, arg1, arg2, ...):
....
fun: function that needs to be converted into a class method
returns: a class method for function.
 A class method is a method that is bound to the class and not the object of the
class.
 They have the access to the state of the class as it takes a class parameter that
points to the class and not the object instance.
 It can modify a class state that would apply across all the instances of the class.
For example, it can modify a class variable that will be applicable to all the
instances.
What is the Static Method in Python?
A static method does not receive an implicit first argument. A static method is also a
method that is bound to the class and not the object of the class. This method can’t access
or modify the class state. It is present in a class because it makes sense for the method to be
present in class.
Syntax Python Static Method:
class C(object):
@staticmethod
def fun(arg1, arg2, ...):
...
returns: a static method for function fun.
Class method vs Static Method
The difference between the Class method and the static method is:
 A class method takes cls as the first parameter while a static method needs no
specific parameters.
 A class method can access or modify the class state while a static method can’t
access or modify it.
 In general, static methods know nothing about the class state. They are utility-
type methods that take some parameters and work upon those parameters. On
the other hand class methods must have class as a parameter.
 We use @classmethod decorator in python to create a class method and we use
@staticmethod decorator to create a static method in python.
When to use the class or static method?
 We generally use the class method to create factory methods. Factory methods
return class objects ( similar to a constructor ) for different use cases.
 We generally use static methods to create utility functions.
How to define a class method and a static method?
To define a class method in python, we use @classmethod decorator, and to define a static
method we use @staticmethod decorator.
Let us look at an example to understand the difference between both of them. Let us say we
want to create a class Person. Now, python doesn’t support method overloading like C+
+ or Java so we use class methods to create factory methods. In the below example we use
a class method to create a person object from birth year.
As explained above we use static methods to create utility functions. In the below example
we use a static method to check if a person is an adult or not.
One simple Example :
class method:
class MyClass:
def __init__(self, value):
self.value = value

def get_value(self):
return self.value

# Create an instance of MyClass


obj = MyClass(10)

# Call the get_value method on the instance


print(obj.get_value()) # Output: 10

Output
10
Static method:-
class MyClass:
def __init__(self, value):
self.value = value

@staticmethod
def get_max_value(x, y):
return max(x, y)

# Create an instance of MyClass


obj = MyClass(10)

print(MyClass.get_max_value(20, 30))

print(obj.get_max_value(20, 30))

Output
30
30
Below is the complete Implementation
# Python program to demonstrate
# use of class method and static method.
from datetime import date

class Person:
def __init__(self, name, age):
self.name = name
self.age = age

# a class method to create a Person object by birth year.


@classmethod
def fromBirthYear(cls, name, year):
return cls(name, date.today().year - year)

# a static method to check if a Person is adult or not.


@staticmethod
def isAdult(age):
return age > 18

person1 = Person('mayank', 21)


person2 = Person.fromBirthYear('mayank', 1996)

print(person1.age)
print(person2.age)

# print the result


print(Person.isAdult(22))

Output:
21
25
True
Python Exception Handling



Error in Python can be of two types i.e. Syntax errors and Exceptions. Errors are problems
in a program due to which the program will stop the execution. On the other hand,
exceptions are raised when some internal events occur which change the normal flow of
the program.
Different types of exceptions in python:
In Python, there are several built-in Python exceptions that can be raised when an error
occurs during the execution of a program. Here are some of the most common types of
exceptions in Python:
 SyntaxError: This exception is raised when the interpreter encounters a syntax
error in the code, such as a misspelled keyword, a missing colon, or an
unbalanced parenthesis.
 TypeError: This exception is raised when an operation or function is applied to
an object of the wrong type, such as adding a string to an integer.
 NameError: This exception is raised when a variable or function name is not
found in the current scope.
 IndexError: This exception is raised when an index is out of range for a list,
tuple, or other sequence types.
 KeyError: This exception is raised when a key is not found in a dictionary.
 ValueError: This exception is raised when a function or method is called with
an invalid argument or input, such as trying to convert a string to an integer
when the string does not represent a valid integer.
 AttributeError: This exception is raised when an attribute or method is not
found on an object, such as trying to access a non-existent attribute of a class
instance.
 IOError: This exception is raised when an I/O operation, such as reading or
writing a file, fails due to an input/output error.
 ZeroDivisionError: This exception is raised when an attempt is made to divide a
number by zero.
 ImportError: This exception is raised when an import statement fails to find or
load a module.
These are just a few examples of the many types of exceptions that can occur in Python.
It’s important to handle exceptions properly in your code using try-except blocks or other
error-handling techniques, in order to gracefully handle errors and prevent the program
from crashing.
Difference between Syntax Error and Exceptions
Syntax Error: As the name suggests this error is caused by the wrong syntax in the code.
It leads to the termination of the program.
Example:
There is a syntax error in the code . The ‘if' statement should be followed by a colon (:),
and the ‘print' statement should be indented to be inside the ‘if' block.
amount = 10000
if(amount > 2999)
print("You are eligible to purchase Dsa Self Paced")

Output:
Exceptions: Exceptions are raised when the program is syntactically correct, but the code
results in an error. This error does not stop the execution of the program, however, it
changes the normal flow of the program.
Example:
Here in this code a s we are dividing the ‘marks’ by zero so a error will occur known
as ‘ZeroDivisionError’
marks = 10000
a = marks / 0
print(a)

Output:

In the above example raised the ZeroDivisionError as we are trying to divide a number by
0.
Note: Exception is the base class for all the exceptions in Python. You can check the
exception hierarchy here.
Example:
1) TypeError: This exception is raised when an operation or function is applied to an
object of the wrong type. Here’s an example:
Here a ‘TypeError’ is raised as both the datatypes are different which are being added.
x=5
y = "hello"
z=x+y

output:
Traceback (most recent call last):
File "7edfa469-9a3c-4e4d-98f3-5544e60bff4e.py", line 4, in <module>
z = x + y
TypeError: unsupported operand type(s) for +: 'int' and 'str'
try catch block to resolve it:
The code attempts to add an integer (‘x') and a string (‘y') together, which is not a valid
operation, and it will raise a ‘TypeError'. The code used a ‘try' and ‘except' block to catch
this exception and print an error message.
x=5
y = "hello"
try:
z=x+y
except TypeError:
print("Error: cannot add an int and a str")

Output
Error: cannot add an int and a str
Try and Except Statement – Catching Exceptions
Try and except statements are used to catch and handle exceptions in Python. Statements
that can raise exceptions are kept inside the try clause and the statements that handle the
exception are written inside except clause.
Example: Here we are trying to access the array element whose index is out of bound and
handle the corresponding exception.
a = [1, 2, 3]
try:
print ("Second element = %d" %(a[1]))

print ("Fourth element = %d" %(a[3]))

except:
print ("An error occurred")

Output
Second element = 2
An error occurred
In the above example, the statements that can cause the error are placed inside the try
statement (second print statement in our case). The second print statement tries to access
the fourth element of the list which is not there and this throws an exception. This
exception is then caught by the except statement.
Catching Specific Exception
A try statement can have more than one except clause, to specify handlers for different
exceptions. Please note that at most one handler will be executed. For example, we can add
IndexError in the above code. The general syntax for adding specific exceptions are –
try:
# statement(s)
except IndexError:
# statement(s)
except ValueError:
# statement(s)
Example: Catching specific exceptions in the Python
The code defines a function ‘fun(a)' that calculates b based on the input a. If a is less than 4,
it attempts a division by zero, causing a ‘ZeroDivisionError'. The code
calls fun(3) and fun(5) inside a try-except block. It handles the ZeroDivisionError for fun(3) and
prints “ZeroDivisionError Occurred and Handled.” The ‘NameError' block is not
executed since there are no ‘NameError' exceptions in the code.
def fun(a):
if a < 4:

b = a/(a-3)
print("Value of b = ", b)

try:
fun(3)
fun(5)
except ZeroDivisionError:
print("ZeroDivisionError Occurred and Handled")
except NameError:
print("NameError Occurred and Handled")

Output
ZeroDivisionError Occurred and Handled
If you comment on the line fun(3), the output will be
NameError Occurred and Handled
The output above is so because as soon as python tries to access the value of b, NameError
occurs.
Try with Else Clause
In Python, you can also use the else clause on the try-except block which must be present
after all the except clauses. The code enters the else block only if the try clause does not
raise an exception.
Try with else clause
The code defines a function AbyB(a, b) that calculates c as ((a+b) / (a-b)) and handles a
potential ZeroDivisionError. It prints the result if there’s no division by zero error.
Calling AbyB(2.0, 3.0) calculates and prints -5.0, while calling AbyB(3.0, 3.0) attempts to divide
by zero, resulting in a ZeroDivisionError, which is caught and “a/b results in 0” is printed.
def AbyB(a , b):
try:
c = ((a+b) / (a-b))
except ZeroDivisionError:
print ("a/b result in 0")
else:
print (c)
AbyB(2.0, 3.0)
AbyB(3.0, 3.0)

Output:
-5.0
a/b result in 0
Finally Keyword in Python
Python provides a keyword finally, which is always executed after the try and except
blocks. The final block always executes after the normal termination of the try block or
after the try block terminates due to some exception.
Syntax:
try:
# Some Code....

except:
# optional block
# Handling of exception (if required)
else:
# execute if no exception

finally:
# Some code .....(always executed)
Example:
The code attempts to perform integer division by zero, resulting in a ZeroDivisionError. It
catches the exception and prints “Can’t divide by zero.” Regardless of the exception,
the finally block is executed and prints “This is always executed.”
try:
k = 5//0
print(k)

except ZeroDivisionError:
print("Can't divide by zero")

finally:
print('This is always executed')

Output:
Can't divide by zero
This is always executed
Raising Exception
The raise statement allows the programmer to force a specific exception to occur. The sole
argument in raise indicates the exception to be raised. This must be either an exception
instance or an exception class (a class that derives from Exception).
This code intentionally raises a NameError with the message “Hi there” using
the raise statement within a try block. Then, it catches the NameError exception, prints “An
exception,” and re-raises the same exception using raise. This demonstrates how exceptions
can be raised and handled in Python, allowing for custom error messages and further
exception propagation.
try:
raise NameError("Hi there")
except NameError:
print ("An exception")
raise

The output of the above code will simply line printed as “An exception” but a Runtime
error will also occur in the last due to the raise statement in the last line. So, the output on
your command line will look like
Traceback (most recent call last):
File "/home/d6ec14ca595b97bff8d8034bbf212a9f.py", line 5, in <module>
raise NameError("Hi there") # Raise Error
NameError: Hi there
Advantages of Exception Handling:
 Improved program reliability: By handling exceptions properly, you can prevent
your program from crashing or producing incorrect results due to unexpected
errors or input.
 Simplified error handling: Exception handling allows you to separate error
handling code from the main program logic, making it easier to read and
maintain your code.
 Cleaner code: With exception handling, you can avoid using complex
conditional statements to check for errors, leading to cleaner and more readable
code.
 Easier debugging: When an exception is raised, the Python interpreter prints a
traceback that shows the exact location where the exception occurred, making it
easier to debug your code.
Disadvantages of Exception Handling:
 Performance overhead: Exception handling can be slower than using
conditional statements to check for errors, as the interpreter has to perform
additional work to catch and handle the exception.
 Increased code complexity: Exception handling can make your code more
complex, especially if you have to handle multiple types of exceptions or
implement complex error handling logic.
 Possible security risks: Improperly handled exceptions can potentially reveal
sensitive information or create security vulnerabilities in your code, so it’s
important to handle exceptions carefully and avoid exposing too much
information about your program.
Overall, the benefits of exception handling in Python outweigh the drawbacks, but it’s
important to use it judiciously and carefully in order to maintain code quality and program
reliability.

User-defined Exceptions in Python with Examples





Example:
class CustomError(Exception):
pass

raise CustomError("Example of Custom Exceptions in Python")

Output: CustomError: Example of Custom Exceptions in Python


Python throws errors and exceptions when the code goes wrong, which may cause the
program to stop abruptly. Python also provides an exception handling method with the help
of try-except. Some of the standard exceptions which are most frequent include IndexError,
ImportError, IOError, ZeroDivisionError, TypeError, and FileNotFoundError.
User-Defined Exception in Python
Exceptions need to be derived from the Exception class, either directly or indirectly.
Although not mandatory, most of the exceptions are named as names that end
in “Error” similar to the naming of the standard exceptions in python. For example,
# A python program to create user-defined exception
# class MyError is derived from super class Exception
class MyError(Exception):

# Constructor or Initializer
def __init__(self, value):
self.value = value

# __str__ is to print() the value


def __str__(self):
return(repr(self.value))

try:
raise(MyError(3*2))

# Value of Exception is stored in error


except MyError as error:
print('A New Exception occurred: ', error.value)

Output
A New Exception occurred: 6
Customizing Exception Classes
To know more about class Exception, run the code below
help(Exception)

Output
Help on class Exception in module exceptions:

class Exception(BaseException)
| Common base class for all non-exit exceptions.
|
| Method resolution order:
| Exception
| BaseException
| __builtin__.object
|
| Methods defined here:
|
| __init__(...)
| x.__init__(...) initializes x; see help(type(x)) for signature
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __new__ = <built-in method __new__ of type object>
| T.__new__(S, ...) -> a new object with type S, a subtype of T
|
| ----------------------------------------------------------------------
| Methods inherited from BaseException:
|
| __delattr__(...)
| x.__delattr__('name') <==> del x.name
|
| __getattribute__(...)
| x.__getattribute__('name') <==> x.name
|
| __getitem__(...)
| x.__getitem__(y) <==> x[y]
|
| __getslice__(...)
| x.__getslice__(i, j) <==> x[i:j]
|
| Use of negative indices is not supported.
|
| __reduce__(...)
|
| __repr__(...)
| x.__repr__() <==> repr(x)
|
| __setattr__(...)
| x.__setattr__('name', value) <==> x.name = value
|
| __setstate__(...)
|
| __str__(...)
| x.__str__() <==> str(x)
|
| __unicode__(...)
|
| ----------------------------------------------------------------------
| Data descriptors inherited from BaseException:
|
| __dict__
|
| args
|
| message
Example 1: User-Defined class with Multiple Inheritance
In the below article, we have created a class named “Error” derived from the class
Exception. This base class is inherited by various user-defined classes to handle different
types of python raise an exception with message
# define Python user-defined exceptions
class Error(Exception):
"""Base class for other exceptions"""
pass

class zerodivision(Error):
"""Raised when the input value is zero"""
pass

try:
i_num = int(input("Enter a number: "))
if i_num == 0:
raise zerodivision
except zerodivision:
print("Input value is zero, try again!")
print()

Output
Enter a number: 0
Input value is zero, try again!
Example 2: Deriving Error from Super Class Exception
Superclass Exceptions are created when a module needs to handle several distinct errors.
One of the common ways of doing this is to create a base class for exceptions defined by
that module. Further, various subclasses are defined to create specific exception classes for
different error conditions.
# class Error is derived from super class Exception
class Error(Exception):

# Error is derived class for Exception, but


# Base class for exceptions in this module
pass

class TransitionError(Error):

# Raised when an operation attempts a state


# transition that's not allowed.
def __init__(self, prev, nex, msg):
self.prev = prev
self.next = nex

# Error message thrown is saved in msg


self.msg = msg

try:
raise(TransitionError(2, 3*2, "Not Allowed"))
# Value of Exception is stored in error
except TransitionError as error:
print('Exception occurred: ', error.msg)

Output
Exception occurred: Not Allowed
How to use standard Exceptions as a base class?
A runtime error is a class that is a standard exception that is raised when a generated error
does not fall into any category. This program illustrates how to use runtime error as a base
class and network error as a derived class. In a similar way, an exception can be derived
from the standard exceptions of Python.
# NetworkError has base RuntimeError
# and not Exception
class Networkerror(RuntimeError):
def __init__(self, arg):
self.args = arg

try:
raise Networkerror("Error")

except Networkerror as e:
print(e.args)

Output
('E', 'r', 'r', 'o', 'r')

Built-in Exceptions in Python





All instances in Python must be instances of a class that derives from BaseException. Two
exception classes that are not related via subclassing are never equivalent, even if they
have the same name. The built-in exceptions can be generated by the interpreter or built-in
functions.
There are several built-in exceptions in Python that are raised when errors occur. These
built-in exceptions can be viewed using the local() built-in functions as follows :
>>> locals()['__builtins__']
This returns a dictionary of built-in exceptions, functions and attributes.
Base Classes
The following exceptions are used mostly as base classes for other exceptions.
1. exception BaseException
This is the base class for all built-in exceptions. It is not meant to be directly
inherited by user-defined classes. For, user-defined classes, Exception is used.
This class is responsible for creating a string representation of the exception
using str() using the arguments passed. An empty string is returned if there are
no arguments.
 args : The args are the tuple of arguments given to the exception
constructor.
 with_traceback(tb) : This method is usually used in exception
handling. This method sets tb as the new traceback for the exception
and returns the exception object.
Code :
try:
...
except SomeException:
tb = sys.exc_info()[2]
raise OtherException(...).with_traceback(tb)
2. exception Exception
This is the base class for all built-in non-system-exiting exceptions. All user-
defined exceptions should also be derived from this class.
3. exception ArithmeticError
This class is the base class for those built-in exceptions that are raised for
various arithmetic errors such as :
 OverflowError
 ZeroDivisionError
 FloatingPointError
Example :
try:
a = 10/0
print (a)
except ArithmeticError:
print ("This statement is raising an arithmetic exception.")
else:
print ("Success.")

Output :
This statement is raising an arithmetic exception.
4. exception BufferError
This exception is raised when buffer related operations cannot be performed.
5. exception LookupError
This is the base class for those exceptions that are raised when a key or index
used on a mapping or sequence is invalid or not found. The exceptions raised are
:
 KeyError
 IndexError
Example :
try:
a = [1, 2, 3]
print (a[3])
except LookupError:
print ("Index out of bound error.")
else:
print ("Success")

Output :
Index out of bound error.
Concrete exceptions
The following exceptions are the exceptions that are usually raised.
1. exception AssertionError
An AssertionError is raised when an assert statement fails.
Example :
assert False, 'The assertion failed'
Output :
Traceback (most recent call last):
File "exceptions_AssertionError.py", line 12, in
assert False, 'The assertion failed'
AssertionError: The assertion failed
2. exception AttributeError
An AttributeError is raised when an attribute reference or assignment fails such
as when a non-existent attribute is referenced.
Example :
class Attributes(object):
pass

object = Attributes()
print (object.attribute)

Output :
Traceback (most recent call last):
File "d912bae549a2b42953bc62da114ae7a7.py", line 5, in
print object.attribute
AttributeError: 'Attributes' object has no attribute 'attribute'
3. exception EOFError
An EOFError is raised when built-in functions like input() hits an end-of-file
condition (EOF) without reading any data. The file methods like readline()
return an empty string when they hit EOF.
Example :
while True:
data = input('Enter name : ')
print ('Hello ', data)

Output :
Enter Name :Hello Aditi
Enter Name :Traceback (most recent call last):
File "exceptions_EOFError.py", line 13, in
data = raw_input('Enter name :')
EOFError: EOF when reading a line
4. exception FloatingPointError
A FloatingPointError is raised when a floating point operation fails. This
exception is always defined, but can only be raised when Python is configured
with the–with-fpectl option, or the WANT_SIGFPE_HANDLER symbol is
defined in the pyconfig.h file.
Example :
import math

print (math.exp(1000))

Output :
Traceback (most recent call last):
File "", line 1, in
FloatingPointError: in math_1
5. exception GeneratorExit
This exception directly inherits from BaseException instead of Exception since it
is technically not an error. A GeneratorExit exception is raised when a
generator or coroutine is closed.
Example :
def my_generator():
try:
for i in range(5):
print ('Yielding', i)
yield i
except GeneratorExit:
print ('Exiting early')

g = my_generator()
print (g.next())
g.close()

Output :
Yielding 0
0
Exiting early
6. exception ImportError
An ImportError is raised when the import statement is unable to load a module
or when the “from list” in from … import has a name that cannot be found.
Example :
import module_does_not_exist
Output :
Traceback (most recent call last):
File "exceptions_ImportError_nomodule.py", line 12, in
import module_does_not_exist
ImportError: No module named module_does_not_exist

Example :
from exceptions import Userexception

Output :
Traceback (most recent call last):
File "exceptions_ImportError_missingname.py", line 12, in
from exceptions import Userexception
ImportError: cannot import name Userexception

7. exception ModuleNotFoundError
This is the subclass of ImportError which is raised by import when a module
could not be found. It is also raised when None is found in sys.modules.
8. exception IndexError
An IndexError is raised when a sequence is referenced which is out of range.
Example :
array = [ 0, 1, 2 ]
print (array[3])

Output :
Traceback (most recent call last):
File "exceptions_IndexError.py", line 13, in
print array[3]
IndexError: list index out of range
9. exception KeyError
A KeyError is raised when a mapping key is not found in the set of existing keys.
Example :
array = { 'a':1, 'b':2 }
print (array['c'])

Output :
Traceback (most recent call last):
File "exceptions_KeyError.py", line 13, in
print array['c']
KeyError: 'c'
10.exception KeyboardInterrupt
This error is raised when the user hits the interrupt key such as Control-C or
Delete.
Example :
try:
print ('Press Return or Ctrl-C:',)
ignored = input()
except Exception, err:
print ('Caught exception:', err)
except KeyboardInterrupt, err:
print ('Caught KeyboardInterrupt')
else:
print ('No exception')

Output :
Press Return or Ctrl-C: ^CCaught KeyboardInterrupt
11.exception MemoryError
This error is raised when an operation runs out of memory.
Example :
def fact(a):
factors = []
for i in range(1, a+1):
if a%i == 0:
factors.append(i)
return factors

num = 600851475143
print (fact(num))

Output :
Traceback (most recent call last):
File "4af5c316c749aff128df20714536b8f3.py", line 9, in
print fact(num)
File "4af5c316c749aff128df20714536b8f3.py", line 3, in fact
for i in range(1, a+1):
MemoryError
12.exception NameError
This error is raised when a local or global name is not found. For example, an
unqualified variable name.
Example :
def func():
print ans

func()

Output :
Traceback (most recent call last):
File "cfba0a5196b05397e0a23b1b5b8c7e19.py", line 4, in
func()
File "cfba0a5196b05397e0a23b1b5b8c7e19.py", line 2, in func
print ans
NameError: global name 'ans' is not defined
13.exception NotImplementedError
This exception is derived from RuntimeError. Abstract methods in user defined
classed should raise this exception when the derived classes override the
method.
Example :
class BaseClass(object):
"""Defines the interface"""
def __init__(self):
super(BaseClass, self).__init__()
def do_something(self):
"""The interface, not implemented"""
raise NotImplementedError(self.__class__.__name__ + '.do_something')

class SubClass(BaseClass):
"""Implements the interface"""
def do_something(self):
"""really does something"""
print (self.__class__.__name__ + ' doing something!')

SubClass().do_something()
BaseClass().do_something()

Output :
Traceback (most recent call last):
File "b32fc445850cbc23cd2f081ba1c1d60b.py", line 16, in
BaseClass().do_something()
File "b32fc445850cbc23cd2f081ba1c1d60b.py", line 7, in do_something
raise NotImplementedError(self.__class__.__name__ + '.do_something')
NotImplementedError: BaseClass.do_something
14.exception OSError([arg])
The OSError exception is raised when a system function returns a system-related
error, including I/O failures such as “file not found” or “disk full” errors.
Example :
def func():
print (ans)

func()

Output :
Traceback (most recent call last):
File "442eccd7535a2704adbe372cb731fc0f.py", line 4, in
print i, os.ttyname(i)
OSError: [Errno 25] Inappropriate ioctl for device
15.exception OverflowError
The OverflowError is raised when the result of an arithmetic operation is out of
range. Integers raise MemoryError instead of OverflowError. OverflowError is
sometimes raised for integers that are outside a required range. Floating point
operations are not checked because of the lack of standardization of floating
point exception handling in C.
Example :
import sys

print ('Regular integer: (maxint=%s)' % sys.maxint)


try:
i = sys.maxint * 3
print ('No overflow for ', type(i), 'i =', i)
except OverflowError, err:
print ('Overflowed at ', i, err)

print()
print ('Long integer:')
for i in range(0, 100, 10):
print ('%2d' % i, 2L ** i)

print()
print ('Floating point values:')
try:
f = 2.0**i
for i in range(100):
print (i, f)
f = f ** 2
except OverflowError, err:
print ('Overflowed after ', f, err)

Output :
Regular integer: (maxint=9223372036854775807)
No overflow for i = 27670116110564327421

Long integer:
01
10 1024
20 1048576
30 1073741824
40 1099511627776
50 1125899906842624
60 1152921504606846976
70 1180591620717411303424
80 1208925819614629174706176
90 1237940039285380274899124224

Floating point values:


0 1.23794003929e+27
1 1.53249554087e+54
2 2.34854258277e+108
3 5.5156522631e+216
Overflowed after 5.5156522631e+216 (34, 'Numerical result out of range')

16.exception RecursionError
The RecursionError is derived from the RuntimeError. This exception is raised
when the interpreter detects that the maximum recursion depth is exceeded.
17.exception ReferenceError
The ReferenceError is raised when a weak reference proxy is used to access an
attribute of the referent after the garbage collection.
Example :
import gc
import weakref

class Foo(object):

def __init__(self, name):


self.name = name

def __del__(self):
print ('(Deleting %s)' % self)

obj = Foo('obj')
p = weakref.proxy(obj)

print ('BEFORE:', p.name)


obj = None
print ('AFTER:', p.name)

Output :
BEFORE: obj
(Deleting )
AFTER:

Traceback (most recent call last):


File "49d0c29d8fe607b862c02f4e1cb6c756.py", line 17, in
print 'AFTER:', p.name
ReferenceError: weakly-referenced object no longer exists
18.exception RuntimeError
The RuntimeError is raised when no other exception applies. It returns a string
indicating what precisely went wrong.
19.exception StopIteration
The StopIteration error is raised by built-in function next() and an iterator‘s
__next__() method to signal that all items are produced by the iterator.
Example :
Arr = [3, 1, 2]
i=iter(Arr)

print (i)
print (i.next())
print (i.next())
print (i.next())
print (i.next())

Output :

3
1
2

Traceback (most recent call last):


File "2136fa9a620e14f8436bb60d5395cc5b.py", line 8, in
print i.next()
StopIteration
20.exception SyntaxError
The SyntaxError is raised when the parser encounters a syntax error. A syntax
error may occur in an import statement or while calling the built-in functions
exec() or eval(), or when reading the initial script or standard input.
Example :
try:
print (eval('geeks for geeks'))
except SyntaxError, err:
print ('Syntax error %s (%s-%s): %s' % \
(err.filename, err.lineno, err.offset, err.text))
print (err)

Output :
Syntax error (1-9): geeks for geeks
invalid syntax (, line 1)
21.exception SystemError
The SystemError is raised when the interpreter finds an internal error. The
associated value is a string indicating what went wrong.
22.exception SystemExit
The SystemExit is raised when sys.exit() function is called. A call to sys.exit() is
translated into an exception to execute clean-up handlers (finally clauses of try
statements) and to debug a script without running the risk of losing control.
23.exception TypeError
TypeError is raised when an operation or function is applied to an object of
inappropriate type. This exception returns a string giving details about the type
mismatch.
Example :
arr = ('tuple', ) + 'string'
print (arr)

Output :
Traceback (most recent call last):
File "30238c120c0868eba7e13a06c0b1b1e4.py", line 1, in
arr = ('tuple', ) + 'string'
TypeError: can only concatenate tuple (not "str") to tuple
24.exception UnboundLocalError
UnboundLocalError is a subclass of NameError which is raised when a
reference is made to a local variable in a function or method, but no value has
been assigned to that variable.
Example :
def global_name_error():
print (unknown_global_name)

def unbound_local():
local_val = local_val + 1
print (local_val)

try:
global_name_error()
except NameError, err:
print ('Global name error:', err)

try:
unbound_local()
except UnboundLocalError, err:
print ('Local name error:', err)

Output :
Global name error: global name 'unknown_global_name' is not defined
Local name error: local variable 'local_val' referenced before assignment
25.exception UnicodeError
This exception is a subclass of ValueError. UnicodeError is raised when a
Unicode-related encoding or decoding error occurs.
26.exception ValueError
A ValueError is raised when a built-in operation or function receives an
argument that has the right type but an invalid value.
Example :
print (int('a'))

Output :
Traceback (most recent call last):
File "44f00efda935715a3c5468d899080381.py", line 1, in
print int('a')
ValueError: invalid literal for int() with base 10: 'a'
27.exception ZeroDivisionError
A ZeroDivisionError is raised when the second argument of a division or
modulo operation is zero. This exception returns a string indicating the type of
the operands and the operation.
Example :
print (1/0)

Output :
Traceback (most recent call last):
File "c31d9626b41e53d170a78eac7d98cb85.py", line 1, in
print 1/0
ZeroDivisionError: integer division or modulo by zero
Python Try Except



Error in Python can be of two types i.e. Syntax errors and Exceptions. Errors are the
problems in a program due to which the program will stop the execution. On the other
hand, exceptions are raised when some internal events occur which changes the normal
flow of the program. Note: For more information, refer to Errors and Exceptions in Python
Some of the common Exception Errors are :
 IOError: if the file can’t be opened
 KeyboardInterrupt: when an unrequired key is pressed by the user
 ValueError: when the built-in function receives a wrong argument
 EOFError: if End-Of-File is hit without reading any data
 ImportError: if it is unable to find the module

Try Except in Python


Try and Except statement is used to handle these errors within our code in Python. The try
block is used to check some code for errors i.e the code inside the try block will execute
when there is no error in the program. Whereas the code inside the except block will
execute whenever the program encounters some error in the preceding try block.

Syntax:
try:
# Some Code
except:
# Executed if error in the
# try block
How try() works?
 First, the try clause is executed i.e. the code between try.
 If there is no exception, then only the try clause will run, except clause is
finished.
 If any exception occurs, the try clause will be skipped and except clause will
run.
 If any exception occurs, but the except clause within the code doesn’t handle it,
it is passed on to the outer try statements. If the exception is left unhandled, then
the execution stops.
 A try statement can have more than one except clause
Code 1: No exception, so the try clause will run.
 Python3
# Python code to illustrate
# working of try()
def divide(x, y):
try:
# Floor Division : Gives only Fractional Part as Answer
result = x // y
print("Yeah ! Your answer is :", result)
except ZeroDivisionError:
print("Sorry ! You are dividing by zero ")

# Look at parameters and note the working of Program


divide(3, 2)

Auxiliary Space: O(1)


Output :
Yeah ! Your answer is : 1
Code 1: There is an exception so only except clause will run.
 Python3
# Python code to illustrate
# working of try()
def divide(x, y):
try:
# Floor Division : Gives only Fractional Part as Answer
result = x // y
print("Yeah ! Your answer is :", result)
except ZeroDivisionError:
print("Sorry ! You are dividing by zero ")

# Look at parameters and note the working of Program


divide(3, 0)

Output :
Sorry ! You are dividing by zero
Code 2: The other way of writing except statement, is shown below and in this way, it
only accepts exceptions that you’re meant to catch or you can check which error is
occurring.
 Python3
# code
def divide(x, y):
try:
# Floor Division : Gives only Fractional Part as Answer
result = x // y
print("Yeah ! Your answer is :", result)
except Exception as e:
# By this way we can know about the type of error occurring
print("The error is: ",e)

divide(3, "GFG")
divide(3,0)

Output:
The error is: unsupported operand type(s) for //: 'int' and 'str'
The error is: integer division or modulo by zero

Else Clause
In Python, you can also use the else clause on the try-except block which must be present
after all the except clauses. The code enters the else block only if the try clause does not
raise an exception.
Syntax:
try:
# Some Code
except:
# Executed if error in the
# try block
else:
# execute if no exception
Code:
 Python3
# Program to depict else clause with try-except

# Function which returns a/b


def AbyB(a , b):
try:
c = ((a+b) // (a-b))
except ZeroDivisionError:
print ("a/b result in 0")
else:
print (c)
# Driver program to test above function
AbyB(2.0, 3.0)
AbyB(3.0, 3.0)

Output:
-5.0
a/b result in 0

Finally Keyword in Python


Python provides a keyword finally, which is always executed after the try and except
blocks. The final block always executes after the normal termination of the try block or
after the try block terminates due to some exceptions.
Syntax:
try:
# Some Code
except:
# Executed if error in the
# try block
else:
# execute if no exception
finally:
# Some code .....(always executed)
Code:
 Python3
# Python program to demonstrate finally

# No exception Exception raised in try block


try:
k = 5//0 # raises divide by zero exception.
print(k)

# handles zerodivision exception


except ZeroDivisionError:
print("Can't divide by zero")

finally:
# this block is always executed
# regardless of exception generation.
print('This is always executed')

Output:
Can't divide by zero
This is always executed
Regular Expression (RegEx) in Python with Examples



A Regular Expression or RegEx is a special sequence of characters that uses a search
pattern to find a string or set of strings.
It can detect the presence or absence of a text by matching it with a particular pattern and
also can split a pattern into one or more sub-patterns.
Regex Module in Python
Python has a built-in module named “re” that is used for regular expressions in Python.
We can import this module by using the import statement.
Example: Importing re module in Python
 Python3
# importing re module
import re

How to Use RegEx in Python?


You can use RegEx in Python after importing re module.
Example:
This Python code uses regular expressions to search for the word “portal” in the given
string and then prints the start and end indices of the matched word within the string.
 Python3
import re

s = 'GeeksforGeeks: A computer science portal for geeks'

match = re.search(r'portal', s)

print('Start Index:', match.start())


print('End Index:', match.end())

Output
Start Index: 34
End Index: 40

Note: Here r character (r’portal’) stands for raw, not regex. The raw string is slightly
different from a regular string, it won’t interpret the \ character as an escape character. This
is because the regular expression engine uses \ character for its own escaping purpose.
Before starting with the Python regex module let’s see how to actually write regex using
metacharacters or special sequences.
Metacharacters
Metacharacters are the characters with special meaning.
To understand the RE analogy, Metacharacters are useful and important. They will be used
in functions of module re. Below is the list of metacharacters.
MetaCharacters Description

Used to drop the special meaning of character


\
following it

[] Represent a character class

^ Matches the beginning

$ Matches the end

. Matches any character except newline

Means OR (Matches with any of the


|
characters separated by it.

? Matches zero or one occurrence

Any number of occurrences (including 0


*
occurrences)

+ One or more occurrences

Indicate the number of occurrences of a


{}
preceding regex to match.

() Enclose a group of Regex

Let’s discuss each of these metacharacters in detail:

1. \ – Backslash
The backslash (\) makes sure that the character is not treated in a special way. This can be
considered a way of escaping metacharacters.
For example, if you want to search for the dot(.) in the string then you will find that dot(.)
will be treated as a special character as is one of the metacharacters (as shown in the above
table). So for this case, we will use the backslash(\) just before the dot(.) so that it will lose
its specialty. See the below example for a better understanding.
Example:
The first search (re.search(r'.', s)) matches any character, not just the period, while the
second search (re.search(r'\.', s)) specifically looks for and matches the period character.
 Python3
import re

s = 'geeks.forgeeks'

# without using \
match = re.search(r'.', s)
print(match)

# using \
match = re.search(r'\.', s)
print(match)

Output
<re.Match object; span=(0, 1), match='g'>
<re.Match object; span=(5, 6), match='.'>

2. [] – Square Brackets
Square Brackets ([]) represent a character class consisting of a set of characters that we
wish to match. For example, the character class [abc] will match any single a, b, or c.
We can also specify a range of characters using – inside the square brackets. For example,
 [0, 3] is sample as [0123]
 [a-c] is same as [abc]
We can also invert the character class using the caret(^) symbol. For example,
 [^0-3] means any number except 0, 1, 2, or 3
 [^a-c] means any character except a, b, or c
Example:
In this code, you’re using regular expressions to find all the characters in the string that fall
within the range of ‘a’ to ‘m’. The re.findall() function returns a list of all such characters. In
the given string, the characters that match this pattern are: ‘c’, ‘k’, ‘b’, ‘f’, ‘j’, ‘e’, ‘h’, ‘l’,
‘d’, ‘g’.
 Python3
import re

string = "The quick brown fox jumps over the lazy dog"
pattern = "[a-m]"
result = re.findall(pattern, string)

print(result)

Output
['h', 'e', 'i', 'c', 'k', 'b', 'f', 'j', 'm', 'e', 'h', 'e', 'l', 'a', 'd', 'g']

3. ^ – Caret
Caret (^) symbol matches the beginning of the string i.e. checks whether the string starts
with the given character(s) or not. For example –
 ^g will check if the string starts with g such as geeks, globe, girl, g, etc.
 ^ge will check if the string starts with ge such as geeks, geeksforgeeks, etc.
Example:
This code uses regular expressions to check if a list of strings starts with “The”. If a string
begins with “The,” it’s marked as “Matched” otherwise, it’s labeled as “Not matched”.
 Python3
import re
regex = r'^The'
strings = ['The quick brown fox', 'The lazy dog', 'A quick brown fox']
for string in strings:
if re.match(regex, string):
print(f'Matched: {string}')
else:
print(f'Not matched: {string}')

Output
Matched: The quick brown fox
Matched: The lazy dog
Not matched: A quick brown fox

4. $ – Dollar
Dollar($) symbol matches the end of the string i.e checks whether the string ends with the
given character(s) or not. For example-
 s$ will check for the string that ends with a such as geeks, ends, s, etc.
 ks$ will check for the string that ends with ks such as geeks, geeksforgeeks, ks,
etc.
Example:
This code uses a regular expression to check if the string ends with “World!”. If a match is
found, it prints “Match found!” otherwise, it prints “Match not found”.
 Python3
import re

string = "Hello World!"


pattern = r"World!$"

match = re.search(pattern, string)


if match:
print("Match found!")
else:
print("Match not found.")

Output
Match found!

5. . – Dot
Dot(.) symbol matches only a single character except for the newline character (\n). For
example –
 a.b will check for the string that contains any character at the place of the dot
such as acb, acbd, abbb, etc
 .. will check if the string contains at least 2 characters
Example:
This code uses a regular expression to search for the pattern “brown.fox” within the string.
The dot (.) in the pattern represents any character. If a match is found, it prints “Match
found!” otherwise, it prints “Match not found”.
 Python3
import re

string = "The quick brown fox jumps over the lazy dog."
pattern = r"brown.fox"

match = re.search(pattern, string)


if match:
print("Match found!")
else:
print("Match not found.")

Output
Match found!

6. | – Or
Or symbol works as the or operator meaning it checks whether the pattern before or after
the or symbol is present in the string or not. For example –
 a|b will match any string that contains a or b such as acd, bcd, abcd, etc.

7. ? – Question Mark
The question mark (?) is a quantifier in regular expressions that indicates that the preceding
element should be matched zero or one time. It allows you to specify that the element is
optional, meaning it may occur once or not at all. For example,
 ab?c will be matched for the string ac, acb, dabc but will not be matched for
abbc because there are two b. Similarly, it will not be matched for abdc because
b is not followed by c.

8.* – Star
Star (*) symbol matches zero or more occurrences of the regex preceding the * symbol. For
example –
 ab*c will be matched for the string ac, abc, abbbc, dabc, etc. but will not be
matched for abdc because b is not followed by c.

9. + – Plus
Plus (+) symbol matches one or more occurrences of the regex preceding the + symbol. For
example –
 ab+c will be matched for the string abc, abbc, dabc, but will not be matched for
ac, abdc, because there is no b in ac and b, is not followed by c in abdc.

10. {m, n} – Braces


Braces match any repetitions preceding regex from m to n both inclusive. For example –
 a{2, 4} will be matched for the string aaab, baaaac, gaad, but will not be
matched for strings like abc, bc because there is only one a or no a in both the
cases.

11. (<regex>) – Group


Group symbol is used to group sub-patterns. For example –
 (a|b)cd will match for strings like acd, abcd, gacd, etc.
Special Sequences
Special sequences do not match for the actual character in the string instead it tells the
specific location in the search string where the match must occur. It makes it easier to write
commonly used patterns.

List of special sequences


Special
Sequence Description Examples

Matches if the for geeks


\A string begins with \Afor
the given character for the world

Matches if the geeks


word begins or
ends with the given
character. \
b(string) will check
\b \bge
for the beginning
of the word and get
(string)\b will
check for the
ending of the word.

It is the opposite of together


the \b i.e. the string
\B should not start or \Bge
end with the given forge
regex.

Matches any 123


decimal digit, this
\d \d
is equivalent to the
set class [0-9] gee1

Matches any non- geeks


digit character, this
\D \D
is equivalent to the
set class [^0-9] geek1
Special
Sequence Description Examples

Matches any gee ks


\s whitespace \s
character. a bc a

Matches any non- a bd


\S whitespace \S
character abcd

Matches any 123


alphanumeric
\w character, this is \w
equivalent to the geeKs4
class [a-zA-Z0-9_].

Matches any non- >$


\W alphanumeric \W
character. gee<>

Matches if the abcdab


\Z string ends with the ab\Z
given regex abababab
RegEx Functions
re module contains many functions that help us to search a string for a match.
Let’s see various functions provided by this module to work with regex in Python.
Function Description

finds and returns all matching occurrences in


re.findall()
a list

Regular expressions are compiled into


re.compile()
pattern objects

Split string by the occurrences of a character


re.split()
or a pattern.
Function Description

Replaces all occurrences of a character or


re.sub()
patter with a replacement string.

re.escape() Escapes special character

Searches for first occurrence of character or


re.search()
pattern

Let’s see the working of these RegEx functions with definition and examples:
1. re.findall()
Return all non-overlapping matches of pattern in string, as a list of strings. The string is
scanned left-to-right, and matches are returned in the order found.
Finding all occurrences of a pattern
This code uses a regular expression (\d+) to find all the sequences of one or more digits in
the given string. It searches for numeric values and stores them in a list. In this example, it
finds and prints the numbers “123456789” and “987654321” from the input string.
 Python3
import re
string = """Hello my Number is 123456789 and
my friend's number is 987654321"""
regex = '\d+'

match = re.findall(regex, string)


print(match)

Output
['123456789', '987654321']

2. re.compile()
Regular expressions are compiled into pattern objects, which have methods for various
operations such as searching for pattern matches or performing string substitutions.
Example 1:
The code uses a regular expression pattern [a-e] to find and list all lowercase letters from ‘a’
to ‘e’ in the input string “Aye, said Mr. Gibenson Stark”. The output will be ['e', 'a', 'd',
'b', 'e'], which are the matching characters.

 Python
import re
p = re.compile('[a-e]')

print(p.findall("Aye, said Mr. Gibenson Stark"))

Output
['e', 'a', 'd', 'b', 'e', 'a']

Understanding the Output:


 First occurrence is ‘e’ in “Aye” and not ‘A’, as it is Case Sensitive.
 Next Occurrence is ‘a’ in “said”, then ‘d’ in “said”, followed by ‘b’ and ‘e’ in
“Gibenson”, the Last ‘a’ matches with “Stark”.
 Metacharacter backslash ‘\’ has a very important role as it signals various
sequences. If the backslash is to be used without its special meaning as
metacharacter, use’\\’
Example 2: Set class [\s,.] will match any whitespace character, ‘,’, or, ‘.’ .
The code uses regular expressions to find and list all single digits and sequences of digits in
the given input strings. It finds single digits with \d and sequences of digits with \d+.
 Python
import re
p = re.compile('\d')
print(p.findall("I went to him at 11 A.M. on 4th July 1886"))

p = re.compile('\d+')
print(p.findall("I went to him at 11 A.M. on 4th July 1886"))

Output
['1', '1', '4', '1', '8', '8', '6']
['11', '4', '1886']

Example 3:
The code uses regular expressions to find and list word characters, sequences of word
characters, and non-word characters in input strings. It provides lists of the matched
characters or sequences.
 Python
import re

p = re.compile('\w')
print(p.findall("He said * in some_lang."))

p = re.compile('\w+')
print(p.findall("I went to him at 11 A.M., he \
said *** in some_language."))

p = re.compile('\W')
print(p.findall("he said *** in some_language."))

Output
['H', 'e', 's', 'a', 'i', 'd', 'i', 'n', 's', 'o', 'm', 'e', '_', 'l', 'a', 'n', 'g']
['I', 'went', 'to', 'him', 'at', '11', 'A', 'M', 'he', 'said', 'in', 'some_language']
[' ', ' ', '*', '*', '*', ' ...

Example 4:
The code uses a regular expression pattern ‘ab*’ to find and list all occurrences of ‘ab’
followed by zero or more ‘b’ characters in the input string “ababbaabbb”. It returns the
following list of matches: [‘ab’, ‘abb’, ‘abbb’].
 Python
import re
p = re.compile('ab*')
print(p.findall("ababbaabbb"))

Output
['ab', 'abb', 'a', 'abbb']

Understanding the Output:


 Our RE is ab*, which ‘a’ accompanied by any no. of ‘b’s, starting from 0.
 Output ‘ab’, is valid because of single ‘a’ accompanied by single ‘b’.
 Output ‘abb’, is valid because of single ‘a’ accompanied by 2 ‘b’.
 Output ‘a’, is valid because of single ‘a’ accompanied by 0 ‘b’.
 Output ‘abbb’, is valid because of single ‘a’ accompanied by 3 ‘b’.
3. re.split()
Split string by the occurrences of a character or a pattern, upon finding that pattern, the
remaining characters from the string are returned as part of the resulting list.
Syntax :
re.split(pattern, string, maxsplit=0, flags=0)

The First parameter, pattern denotes the regular expression, string is the given string in
which pattern will be searched for and in which splitting occurs, maxsplit if not provided is
considered to be zero ‘0’, and if any nonzero value is provided, then at most that many
splits occur. If maxsplit = 1, then the string will split once only, resulting in a list of length
2. The flags are very useful and can help to shorten code, they are not necessary
parameters, eg: flags = re.IGNORECASE, in this split, the case, i.e. the lowercase or the
uppercase will be ignored.
Example 1:
Splits a string using non-word characters and spaces as delimiters, returning
words: ['Words', 'words', 'Words']. Considers apostrophes as non-word characters: ['Word', 's',
'words', 'Words']. Splits using non-word characters and digits: ['On', '12th', 'Jan', '2016', 'at', '11',
'02', 'AM']. Splits using digits as the delimiter: ['On ', 'th Jan ', ', at ', ':', ' AM'].

 Python
from re import split

print(split('\W+', 'Words, words , Words'))


print(split('\W+', "Word's words Words"))
print(split('\W+', 'On 12th Jan 2016, at 11:02 AM'))
print(split('\d+', 'On 12th Jan 2016, at 11:02 AM'))

Output
['Words', 'words', 'Words']
['Word', 's', 'words', 'Words']
['On', '12th', 'Jan', '2016', 'at', '11', '02', 'AM']
['On ', 'th Jan ', ', at ', ':', ' AM']

Example 2:
First statement splits the string at the first occurrence of one or more digits: ['On ', 'th Jan
2016, at 11:02 AM']. second splits the string using lowercase letters a to f as delimiters, case-
insensitive: ['', 'y, ', 'oy oh ', 'oy, ', 'ome here']. Third splits the string using lowercase letters a
to f as delimiters, case-sensitive: ['', 'ey, Boy oh ', 'oy, ', 'ome here'].
 Python
import re
print(re.split('\d+', 'On 12th Jan 2016, at 11:02 AM', 1))
print(re.split('[a-f]+', 'Aey, Boy oh boy, come here', flags=re.IGNORECASE))
print(re.split('[a-f]+', 'Aey, Boy oh boy, come here'))

Output
['On ', 'th Jan 2016, at 11:02 AM']
['', 'y, ', 'oy oh ', 'oy, ', 'om', ' h', 'r', '']
['A', 'y, Boy oh ', 'oy, ', 'om', ' h', 'r', '']

4. re.sub()
The ‘sub’ in the function stands for SubString, a certain regular expression pattern is
searched in the given string(3rd parameter), and upon finding the substring pattern is
replaced by repl(2nd parameter), count checks and maintains the number of times this
occurs.
Syntax:
re.sub(pattern, repl, string, count=0, flags=0)

Example 1:
 First statement replaces all occurrences of ‘ub’ with ‘~*’ (case-
insensitive): 'S~*ject has ~*er booked already'.
 Second statement replaces all occurrences of ‘ub’ with ‘~*’ (case-
sensitive): 'S~*ject has Uber booked already'.
 Third statement replaces the first occurrence of ‘ub’ with ‘~*’ (case-
insensitive): 'S~*ject has Uber booked already'.
 Fourth replaces ‘AND’ with ‘ & ‘ (case-insensitive): 'Baked Beans & Spam'.

 Python
import re
print(re.sub('ub', '~*', 'Subject has Uber booked already',
flags=re.IGNORECASE))
print(re.sub('ub', '~*', 'Subject has Uber booked already'))
print(re.sub('ub', '~*', 'Subject has Uber booked already',
count=1, flags=re.IGNORECASE))
print(re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam',
flags=re.IGNORECASE))

Output
S~*ject has ~*er booked already
S~*ject has Uber booked already
S~*ject has Uber booked already
Baked Beans & Spam

5. re.subn()
subn() is similar to sub() in all ways, except in its way of providing output. It returns a
tuple with a count of the total of replacement and the new string rather than just the string.
Syntax:
re.subn(pattern, repl, string, count=0, flags=0)
Example:
re.subn() replaces all occurrences of a pattern in a string and returns a tuple with the
modified string and the count of substitutions made. It’s useful for both case-sensitive and
case-insensitive substitutions.
 Python
import re

print(re.subn('ub', '~*', 'Subject has Uber booked already'))

t = re.subn('ub', '~*', 'Subject has Uber booked already',


flags=re.IGNORECASE)
print(t)
print(len(t))
print(t[0])

Output
('S~*ject has Uber booked already', 1)
('S~*ject has ~*er booked already', 2)
2
S~*ject has ~*er booked already

6. re.escape()
Returns string with all non-alphanumerics backslashed, this is useful if you want to match
an arbitrary literal string that may have regular expression metacharacters in it.
Syntax:
re.escape(string)

Example:
re.escape() is used to escape special characters in a string, making it safe to be used as a
pattern in regular expressions. It ensures that any characters with special meanings in
regular expressions are treated as literal characters.
 Python
import re
print(re.escape("This is Awesome even 1 AM"))
print(re.escape("I Asked what is this [a-9], he said \t ^WoW"))

Output
This\ is\ Awesome\ even\ 1\ AM
I\ Asked\ what\ is\ this\ \[a\-9\]\,\ he\ said\ \ \ \^WoW
7. re.search()
This method either returns None (if the pattern doesn’t match), or a re.MatchObject
contains information about the matching part of the string. This method stops after the first
match, so this is best suited for testing a regular expression more than extracting data.
Example: Searching for an occurrence of the pattern
This code uses a regular expression to search for a pattern in the given string. If a match is
found, it extracts and prints the matched portions of the string.
In this specific example, it searches for a pattern that consists of a month (letters) followed
by a day (digits) in the input string “I was born on June 24”. If a match is found, it prints
the full match, the month, and the day.
 Python3
import re
regex = r"([a-zA-Z]+) (\d+)"

match = re.search(regex, "I was born on June 24")


if match != None:
print ("Match at index %s, %s" % (match.start(), match.end()))
print ("Full match: %s" % (match.group(0)))
print ("Month: %s" % (match.group(1)))
print ("Day: %s" % (match.group(2)))

else:
print ("The regex pattern does not match.")

Output
Match at index 14, 21
Full match: June 24
Month: June
Day: 24

SETS
A Set is a set of characters enclosed in ‘[]’ brackets. Sets are used to match a single
character in the set of characters specified between brackets. Below is the list of Sets:
Set Description

Quantifies the preceding character or group


\{n,\}
and matches at least n occurrences.

Quantifies the preceding character or group


*
and matches zero or more occurrences.
Set Description

[0123] Matches the specified digits (0, 1, 2, or 3)

matches for any character EXCEPT a, r, and


[^arn]
n

\d Matches any digit (0-9).

matches for any two-digit numbers from 00


[0-5][0-9]
and 59

Matches any alphanumeric character (a-z, A-


\w
Z, 0-9, or _).

Matches any lower case alphabet between a


[a-n]
and n.

\D Matches any non-digit character.

matches where one of the specified characters


[arn]
(a, r, or n) are present

matches any character between a and z, lower


[a-zA-Z]
case OR upper case

[0-9] matches any digit between 0 and 9

Match Object
A Match object contains all the information about the search and the result and if there is
no match found then None will be returned. Let’s see some of the commonly used methods
and attributes of the match object.

1. Getting the string and the regex


match.re attribute returns the regular expression passed and match.string attribute returns
the string passed.
Example: Getting the string and the regex of the matched object
The code searches for the letter “G” at a word boundary in the string “Welcome to
GeeksForGeeks” and prints the regular expression pattern (res.re) and the original
string (res.string).
 Python3
import re
s = "Welcome to GeeksForGeeks"
res = re.search(r"\bG", s)

print(res.re)
print(res.string)

Output
re.compile('\\bG')
Welcome to GeeksForGeeks

2. Getting index of matched object


 start() method returns the starting index of the matched substring
 end() method returns the ending index of the matched substring
 span() method returns a tuple containing the starting and the ending index of the
matched substring
Example: Getting index of matched object
The code searches for the substring “Gee” at a word boundary in the string “Welcome to
GeeksForGeeks” and prints the start index of the match ( res.start()), the end index of the
match (res.end()), and the span of the match (res.span()).
 Python3
import re

s = "Welcome to GeeksForGeeks"

res = re.search(r"\bGee", s)

print(res.start())
print(res.end())
print(res.span())

Output
11
14
(11, 14)
3. Getting matched substring
group() method returns the part of the string for which the patterns match. See the below
example for a better understanding.
Example: Getting matched substring
The code searches for a sequence of two non-digit characters followed by a space and the
letter ‘t’ in the string “Welcome to GeeksForGeeks” and prints the matched text
using res.group().
 Python3
import re
s = "Welcome to GeeksForGeeks"
res = re.search(r"\D{2} t", s)
print(res.group())

Output
me t

In the above example, our pattern specifies for the string that contains at least 2 characters
which are followed by a space, and that space is followed by a t.

You might also like