PYTHON PROGRAMMING
Subject Code : 1BPLC105B CIE Marks : 50
Lecture Hours : 40 (T) 24 (P) SEE Marks : 50
Credits : 04
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Module -3
Dictionaries: Dictionary operations, dictionary methods,
aliasing and copying.
Numpy: About, Shape, Slicing, masking, Broadcasting, dtype.
Files: About files, writing our first file, reading a file line-at-a-time,
turning a file into a list of lines, Reading the whole file at once,
working with binary files, Directories, fetching something from
the Web.
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
- Dictionaries are yet another kind of compound type
- Dictionaries are Python’s built-in mapping type
- They map keys to any immutable type values
- The empty dictionary is denoted { }:
- Create a empty dictionary and add key : value pairs
>>> english_kannada = {}
>>> english_kannada["one"] = “ondu"
>>> english_kannada ["two"] = “eradu“
>>> print(english_kannada)
{"two": “ondu", "one": “eradu"}
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Hashing
- Why dictionaries ?
- Answer: - Dictionaries are very fast
- Implemented using a technique called hashing
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
- Another way of creating dictionary is
>>> english_kannada = {"one": "ondu", "two": “eradu", "three": “mooru"}
- we use a key to look up the corresponding value
>>> print(english_kannada["two"])
‘eradu'
- Dictionary will not store elements in sequence, so we can’t index or slice a
dictionary.
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Dictionary Operations
- The del statement removes a key:value pair from a dictionary
>>> inventory = {"apples": 430, "bananas": 312, "oranges": 525, "pears": 217}
>>> print(inventory)
{'pears': 217, 'apples': 430, 'oranges': 525, 'bananas': 312}
- If someone buys all of the bananas, we can remove the entry from the
dictionary:
>>> del inventory["bananas"]
>>> print(inventory)
{'apples': 430, 'oranges': 525, 'pears': 217}
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Dictionary Operations
- If we want to add new item, can add as follows
>>> inventory["bananas"] = 0
>>> print(inventory)
{'pears': 217, 'apples': 430, 'oranges': 525, 'bananas': 0}
- If we want to change value of existing item, can do as follows
>>> inventory["bananas"] += 200
>>> print(inventory)
{'pears': 0, 'apples': 430, 'oranges': 525, 'bananas': 200}
- The len function returns the number of key:value pairs in dictionary:
>>> len(inventory)
4
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Dictionary Methods
- Dictionaries have a number of useful built-in methods
- The keys method returns keys
for key in english_kannada.keys():
print("Got key", key, "which maps to value", english_kannada[key])
keys = list(english_kannada.keys())
print(keys)
Output: Got key three which maps to value mooru
Got key two which maps to value eradu
Got key one which maps to value ondu
['three', 'two', 'one']
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Dictionary Methods
- Dictionaries have a number of useful built-in methods
- The values method returns values
- It returns a view object which can be turned into a list
>>> list(english_kannada.values())
[‘mooru', ‘eradu', 'ondu']
- The items method also returns a view, which promises a list of tuples— one
tuple for each key:value pair: >>> list(english_kannada.items())
[('three', ‘mooru'), ('two', ‘eradu'), ('one', 'ondu')]
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Dictionary Methods
- The in and not in operators can test if a key is in the dictionary
>>> "one" in english_kannada
True
>>> "six" in english_kannada
False
>>> “mooru" in english_kannada >>> english_kannada["dog"]
False Traceback (most recent call last):
...
KeyError: 'dog'
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Aliasing and copying
- Dictionaries are mutable, we need to be aware of aliasing
- When two variables refer to same object, changes to one affect the other
- If we want to modify a dictionary, keep copy of original, use the copy method
>>> opposites = {"up": "down", "right": "wrong", "yes": "no"}
>>> alias = opposites
>>> copy = [Link]() # Shallow copy
- alias and opposites refer to the same object
- copy refers to a fresh copy of the same dictionary
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Aliasing and copying
>>> opposites = {"up": "down", "right": "wrong", "yes": "no"}
>>> alias = opposites
>>> copy = [Link]() # Shallow copy
- If we modify alias, opposites is also changed, but copy does not
>>> alias["right"] = "left"
>>> opposites["right"]
'left'
- If we modify copy, opposites is unchanged: >>> copy["right"] = "privilege"
>>> opposites["right"]
'left'
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Counting Letters
- If we want to count the number of occurrences of a letter in a string
- How to count?
- A more general version of this problem is to form a frequency table of the
letters in the string (ie. how many times each letter appears)
- Dictionaries provide an elegant way to generate a frequency table
>>> letter_counts = {}
>>> for letter in "Mississippi":
letter_counts[letter] = letter_counts.get(letter, 0) + 1
>>> letter_counts
{'M': 1, 's': 4, 'p': 2, 'i': 4}
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Dictionaries
Counting Letters
>>> letter_counts = {}
>>> for letter in "Mississippi":
letter_counts[letter] = letter_counts.get(letter, 0) + 1
>>> letter_counts
{'M': 1, 's': 4, 'p': 2, 'i': 4}
- Let’s display the frequency table in alphabetical order
- We can do that with the items and sort methods
>>> letter_items = list(letter_counts.items())
>>> letter_items.sort()
>>> print(letter_items)
[('M', 1), ('i', 4), ('p', 2), ('s', 4)]
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
- The standard Python data types are not very suited for mathematical
operations
For example, suppose we have the list a = [2, 3, 8], If we multiply this list by an
integer, we get: >>> a = [2, 3, 8]
>>> 2 * a
[2, 3, 8, 2, 3, 8]
- And float’s are not even allowed
>>> a = [2, 3, 8]
>>> 2 * a
>>> 2.1 * a
TypeError: can't multiply sequence by non-int of type 'float'
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
- In order to solve this using Python lists, we would have to do something like:
values = [2, 3, 8]
result = [ ]
for x in values:
[Link](2.1 * x)
- This is not very elegant, is it?, because they are purely a collection of items
- In order to get a type of list which behaves like a mathematical array or matrix,
we use Numpy.
>>> import numpy as np
>>> a = [Link]([2, 3, 8])
>>> 2.1 * a
array([ 4.2, 6.3, 16.8])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
>>> import numpy as np
>>> a = [Link]([2, 3, 8])
>>> 2.1 * a
array([ 4.2, 6.3, 16.8])
- We abbreviated numpy to np
- [Link] takes a Python list as argument
- The list [2, 3, 8] contains int’s, yet the result contains float’s
- This means numpy changed the data type automatically
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
- Let’s multiply together array’s, what happens?
>>> import numpy as np
>>> a = [Link]([2, 3, 8])
>>> a * a
array([ 4, 9, 64])
>>> a**2
array([ 4, 9, 64])
Note: - numpy arrays are not vectors in the algebraic sense.
- Arithmetic operations between arrays are performed element-wise,
not on the arrays as a whole
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
- To tell numpy we want the dot product we simply use the [Link] function
>>> a = [Link]([2, 3, 8])
>>> [Link](a,a)
77
- If you pass 2D arrays to [Link] it will behave like matrix multiplication
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Shape
- One of the most important properties an array is its shape
- We have already seen 1 dimensional (1D) arrays, but arrays can have any
dimensions
>>> import numpy as np import numpy as np
>>> a = [Link]([2, 3, 8]) >>> b = [Link]([
>>> [Link] [2, 3, 8],
(3,) [4, 5, 6],
])
>>> [Link]
(2, 3)
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Shape
- One of the most important properties an array is its shape
- We have already seen 1 dimensional (1D) arrays, but arrays can have any
dimensions
>>> import numpy as np import numpy as np
>>> a = [Link]([2, 3, 8]) >>> b = [Link]([
>>> [Link] [2, 3, 8],
(3,) [4, 5, 6],
])
>>> [Link]
(2, 3)
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Slicing
- Just like lists, we want to select certain values from an array
- For 1D arrays it works just like for normal python lists
>>> a = [Link]([2, 3, 8])
>>> a[2]
8
>>> a[1:]
[Link]([3, 8])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Slicing
- When dealing with higher dimensional arrays >>> b = [Link]([
[2, 3, 8],
[4, 5, 6],
])
- We see that using b[1] returns the 1th row along the first dimension
>>> b[1]
array([4, 5, 6])
- We can select individual items as
>>> b[1][2] or >>> b[1, 2]
6 6
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Slicing
>>> b = [Link]([
[2, 3, 8],
[4, 5, 6],
])
- If want specific column of values instead of the first row, what to do?
- Then we use : to select all items along the first dimension,
- And then a 1:
>>> b[:, 1]
array([3, 5])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Masking
- Suppose we have an array, and we want to throw away all values above a
certain cutoff, traditional mechanism is as below
>>> a = [Link]([230, 10, 284, 39, 76])
- Set all the values above 200 >>> cutoff = 200
to zero >>> new_a = []
>>> for x in a:
>>> if x > cutoff:
>>> new_a.append(0)
>>> else:
>>> new_a.append(x)
>>> a = [Link](new_a)
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Masking
- But python gives special feature to do that, as below
>>> a = [Link]([230, 10, 284, 39, 76])
>>> cutoff = 200
>>> a > cutoff
[Link]([True, False, True, False, False])
>>> a = [Link]([230, 10, 284, 39, 76])
>>> cutoff = 200
>>> a[ a > cutoff ] = 0
>>> a
[Link]([0, 10, 0, 39, 76])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting
- Broadcasting is the powerful feature within the NumPy library
- That allows for arithmetic operations on arrays of different shapes and sizes
- It provides a mechanism for performing element-wise operations efficiently
without explicitly creating copies of data
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting >>> a = [Link]([
- Example: The shapes of a and b don’t match [ 0, 0, 0],
[10,10,10],
- To proceed, Numpy will stretch b into a [20,20,20],
second dimension [30,30,30],
])
- The operation then takes place element-wise.
>>> b = [Link]([0, 1, 2])
>>> a + b
array([[ 0, 1, 2],
[ 10, 11, 12],
[ 20, 21, 22],
[30, 31, 32]])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting
- Rules of broadcasting >>> a = [Link]([
1) only dimensions of size 1 can be stretched [0, 1],
Example: b is 1D, and has shape (2,) [2, 3],
[4, 5],
- For broadcasting with a, Numpy adds another ])
dimension of size 1 to b. >>> b = [Link]([10, 100])
- Now b has shape (1, 2) >>> a * b
- This new dimension can now be stretched array([[ 0, 100],
[ 20, 300],
three times, so that b’s shape matches a’s [ 40, 500]])
shape of (3, 2).
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting
- Rules of broadcasting >>> a = [Link]([
2) Dimensions are compared from the last to [0, 1],
[2, 3],
the first [4, 5],
- Any dimensions that do not match must be ])
>>> b = [Link]([10, 100])
stretched to become equally sized
>>> a * b
array([[ 0, 100],
[ 20, 300],
[ 40, 500]])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting >>> a = [Link]([
[ 0, 0, 0],
- Some shapes cannot broadcast and Numpy [10,10,10],
will give you an error [20,20,20],
[30,30,30],
])
>>> b = [Link]([1, 2, 3, 4])
>>> a + b
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting
- Some shapes cannot broadcast and Numpy will give you an error
>>> c = [Link]([
[0, 1, 2],
[3, 4, 5],
])
>>> b = [Link]([10, 100])
>>> c * b
ValueError: operands could not be broadcast together with shapes (2,3) (2,)
- Numpy, again, adds a dimension to b, making it of shape (1, 2).
- The sizes of the last dimensions of b and c (2 and 3, respectively) are then
compared and found to differ.
- Since none of these dimensions is of size 1 (therefore, unstretchable) Numpy
gives up and produces an error.
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Broadcasting
- The solution to multiplying c and b above is to specifically tell Numpy that it
must add that extra dimension as the second dimension of b.
- This is done by using None to index that second dimension
- The shape of b then becomes (2,1), which is compatible for broadcasting with c
>>> c = [Link]([
[0, 1, 2],
[3, 4, 5],
])
>>> b = [Link]([10, 100])
>>> c * b[:, None]
array([[ 0, 10, 20],
[300, 400, 500]])
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
dtype
- A commonly used term in working with numpy is dtype - short for data type
- This is typically int or float, followed by some number, e.g. int8.
- This means the value is integer with a size of 8 bits
Example: Each bit is either 0 or 1, With 8 of them, we have 28 = 256 possible
values
Since we also have to count zero itself, the largest possible value is 255
The data type we have now described is called uint8, where the u stands for
unsigned, only positive values are allowed
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
dtype
- If we want to allow negative numbers we use int8.
- The range then shifts to -128 to +127
- An int64 for example is a 64 bit unsigned integer with a range of -
9223372036854775808 to 9223372036854775807
It is also the standard type on a 64 bits machine
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
dtype
What happens when you set numbers bigger than the maximum value of your
dtype?
>>> import numpy as np
>>> a = [Link]([200], dtype='uint8')
>>> a + a
array([144], dtype=uint8)
>>> import numpy as np
>>> a = [Link]([200], dtype='uint16')
>>> a + a
array([400], dtype=uint16)
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga
Numpy
Changing dtype
To change the dtype of an existing array, you can use the astype method
>>> import numpy as np
>>> a = [Link]([200], dtype='uint8')
>>> [Link]('uint64')
Aruna Kumar P
Dept. of ISE, JNNCE, Shivamogga