Python

Python – A Refresher

Operations team reviewing cloud metrics
Photo: Luke Chesser / Unsplash · Royalty-free

Python – Part 1 of 5

  • What is Python and Why:
    • open source programming language
    • interpreted at run-time(unlike compiled Java, C#, like PHP, Perl)
    • Object oriented( like Java and C#)
    • precise and interactive( very short and precise commands, thus easy to learn)
    • Yet it is one of the most powerful languages in Big Data ( roughly 55-60% Big data scripts and programs are written in Python followed by Java and others
    • It is portable (can be run on lot of hardware and software platforms)
    • support a very broad standard library, modules
    • dynamic data types, garbage collection, interfaces to all major databases
    • comes in 2 major versions – Python 2.x (e.g. Python 2.7) and Python 3 – till date most of the Python programs are written in Python 2.x so it is better to learn Python 2.7 first.)
    • One more big thing about Python 2.x is that it can import the features of Python 3 by using ( from __future__ import <import_module> syntax, e.g from __future__ import division imports division from Python 3. In Python 2.x if you divide 3/2 you will get answer as 1 as Python 2 performs basic division. In Python 3, it performs true division , if you divide 3/2 you get 1.5) :
  • Python Setup:
    • Since supported by multiple hardware and software platforms, it can be installed in multiples ways
    • Lets focus Installation on Linux
      • Method one – Install Python on Linuc and use Python Shell(command line)
        • Install Python – yum -y install python27
        • Create a python script file – echo “print ‘hello'” > hello.py
        • Execute the python script in Python shell – python hello.py
        • Directly execute commands on Python shell –
          • get python version – python –version
          • print a statement – print “hello”
          • print 3/2 – returns 1 (because Python 2.x does not perform true division, you have to use something like 3.0/2 to get correct answer. One of the rare language which is kind of forward compatible.)
          • print 3.0/2 – returns 1.5
          • To import true division from Python 3.0 – from __future_ import division
          • Now print 3/2 – returns 1.5
          • to quit Python shell – quit()
        • exIhw
      • Method two– setup –  Jupyter Notebooks – on your local system
        • Install Anaconda(Anaconda installs Python, Jupyter notebooka dn required dependencies as a package) from https://www.anaconda.com/download/
        • It has links for Windows, Linux or Mac installations for Python 2.7 as well as 3.6
        • Lets install Python 2.7 using Windows Installer from https://repo.continuum.io/archive/Anaconda2-5.0.1-Windows-x86_64.exe. Download and install Anaconda.
        • exIhw
        • Anaconda is installed now, verify it by opening Anaconda Navigator, from your Windows Start menu.
        • exIhw
        • Click open the “Jupyter notebook“. It will open in the browser locally:
        • exIhw
        • Now run a few commands on the local instance of your Jupyter notebook.
        • exIhw
      • Method three– Use online tool –  Jupyter Notebooks to interactively learn Python ( https://try.jupyter.org/)
        • exIhw
          Click on “New” button and then on “Python 3” to create a new Python Notebook
        • The Jupyter notebook is a very interactive Python interpreter tool.
        • Type the command in the cell  and press “Shift+Enter” to view results.
        • To see help about a command, first type the command and then press (Shift+Tab)
        • exIhw

  Python – Part 2 of 5

  • Numbers and Strings:
    • Python supports dynamic datatypes i.e. the type of a variable is decided by the values it holds .
    • if we assign a variable a=”Naeem”, then a is a string, if a = “9” then its a number and if a=3.0 then its a float
  • Number Operations:
  • a=5 # assign variables
    b=2
    c=a+b #addition
    print (c)
    7c=a-b #subtraction
    print (c)
    3c=a*b #multiplication
    print (c)
    10c=a/b #division
    print (c)
    2c=5**2 #exponentiation/power of
    print (c)
    25c=5**(1.0/2) #square root
    print (c)
    c=5**(1.0/3) #cube root
    print (c)
    2.2360679775
    1.70997594668c= 2 + 5 * 5 – 3 # order of operation i.e 2 + 25 -3 = 27 -3 = 24
    print (c)
    c= (2 + 5) * (5 – 3) # order of operation i.e 7 * 2 = 14
    print (c)
    c= 2 + 5 * 5 – 3 # order of operation i.e 2 + 25 -3 = 27 -3 = 24
    print (c)
    c= (2 + 5) * (5 – 3) # order of operation i.e 7 * 2 = 14
    print (c)
    24
    14

exIhw

  • True(Python 3.x) vs Basic Division(Python 2.x):

print 3/2
1

print 3.0/2
1.5

from __future__ import division
print 3/2
1.5

exIhw

  • String Operations:

# string assignments
str = “Naeem” # single word
print str
Naeem

str = “Mohd Naeem”
str = “Mohd Naeem” # multiple words
print str
Mohd Naeem

str = “Mohd’s Profile” # single quote is a string
print str
str = ‘Mohd Naeem said and I quote “Big Data is going to revotionalize everything”.’ # double quote in a string
print str
Mohd’s Profile
Mohd Naeem said and I quote “Big Data is going to revotionalize everything”.

# len method
str = “Mohd Naeem”
strlen = len(str)
print (“My Name is %s characters long.” %(strlen))
My Name is 10 characters long.

# In Python strings are sequences, so we can apply index to it ( index begins at 0)
print(str[0]) # M
print(str[5]) # N
M
NexIhw

           

#Using a : to perform slicing to get everything up to a specified point
print(str[1:]) #get all after from Index 1 — ohd Naeem
print(str[5:]) #get all after from Index 5 — Naeem
ohd Naeem
Naeem

print(str[:1]) #get 1 character from reverse(begining) — M
print(str[:4]) #get 4 character from reverse(begining) — Mohd
print(str[:]) #get all characters — Mohd Naeem
M
Mohd
Mohd Naeem

print(str[:-1]) #get all but last — Mohd Naee
print(str[:-5]) #get all but last 5 — Mohd
Mohd Naee
Mohd

print(str[::1]) #get everything with step of 1 — Mohd Naeem
print(str[::2]) #get everything with step of 2 — Mh ae
Mohd Naeem
Mh ae

print(str[::-1]) #reverse a string — meeaN dhoM
print(str[::-2]) #reverse a string with step of 2 — meeaN dhoM
meeaN dhoM
meNdo

exIhw

str = str + ” is my name.” #concatevate strings
print str
print “#”*30 # repeat a charcter here repeating ‘#’ 30 times
Mohd Naeem is my name.
##############################

print str.upper() # to uppercase
print str.lower() # to lowercase
print str.title() # to titlecase
​MOHD NAEEM IS MY NAME.
mohd naeem is my name.
Mohd Naeem Is My Name.

substituion is not needed
#print formatting – using {} placeholders – order of variable substituion is not needed
strName = “My first name is {} and last name is {}. “.format(“Mohd”, “Naeem”)
print(strName)
strName = “My age is {age} and I live in {city}. “.format(age=”35″, city=”Frisco”)
print(strName)
My first name is Mohd and last name is Naeem.
My age is 35 and I live in Frisco.

#print formatting – using % placeholders – order of variable substitution is a must
strName = “My name is %s. ” %(“Naeem”) # substitute 1 string
print(strName)
strName = “My first name is %s and last name is %s. ” %(“Mohd”,”Naeem”) # substitute multiple strings
print(strName)
strNumbers = “My age is %d ” %(35) # # substitute 1 number
print(strNumbers)
strNumbers = “My age is %d and her age is %d ” %(35, 30) # # substitute multiple numbers
print(strNumbers)
strNumbers = “My age is %1.2f ” %(33.144) # substituting floating point numbers ( min 1 digit before decimal, max 2 digit after)
print(strNumbers)
strNumbers = “My age is %1.0f ” %(33.144) # substituting floating point numbers ( min 1 digit before decimal, max 0 digit after)
print(strNumbers)
strNumbers = “My age is %1.5f ” %(33.144) # substituting floating point numbers ( min 1 digit before decimal, max 5 digit after)
print(strNumbers)
strNumbers = “My age is %9.8f ” %(33.144) # substituting floating point numbers ( min 9 digit before decimal, max 8 digit after)
print(strNumbers)
My name is Naeem.
My first name is Mohd and last name is Naeem.
My age is 35
My age is 35 and her age is 30
My age is 33.14
My age is 33
My age is 33.14400
My age is 33.14400000

exIhw

                   

  • The strings are immutable(can’t be changed by index)
    • E.g. str= “naeem” and try s[0]=”N”, you will get error.
  • This means that one created you can’t update a string by it’s index and thus string are immutable.exIhw

       

  • Lists : they are mutable sequence
  • # creating a list of numbers
    lst = [1,2,3,4,5]
    print lst
    [1, 2, 3, 4, 5]# creating a list of string
    lst = [“red”, “blue”, “green”]
    print lst
    [‘red’, ‘blue’, ‘green’]# creating a list of mixed objects
    lst = [1, “one”, 2, “two”]
    print lst
    [1, ‘one’, 2, ‘two’]# getting the length of a string using len() function
    ln = len(lst)
    print ln
    4print lst
    # adding more members to list, thus lists are mutable
    lst = lst + [3, “three”]
    print lst
    [1, ‘one’, 2, ‘two’, 3, ‘three’]

exIhw

           

#indexing and slicing in a list
print lst[0] # 1st member
print lst[5] # 6th member
1
three

print lst[1:] # all members except 1st
print lst[:3] # all members up to the 3rd
​[‘one’, 2, ‘two’, 3, ‘three’]
[1, ‘one’, 2]

print lst[::-1] # reverse the list
print lst[::-2] # reverse the list by steps of 2
[‘three’, 3, ‘two’, 2, ‘one’, 1]
[‘three’, ‘two’, ‘one’]

# doubling a list by mutiplying the list by 2
lst = lst * 2 # doubling a list by mutiplying the list by 2
print (lst)
[1, ‘one’, 2, ‘two’, 3, ‘three’, 1, ‘one’, 2, ‘two’, 3, ‘three’]

# using append methid to add members to list
newlist =[]
newlist.append(1)
newlist.append(“two”)
newlist.append(3)
print newlist
[1, ‘two’, 3]

exIhw

       

lst=[3,2,1]
print lst # [3,2,1] – pops the last item
print lst.pop() # pops ‘1’ out
print lst # [3,2]
lst=[‘i’,’a’,’e’,’u’,’o’]
print lst.pop(2) # pops ‘e’ out
print lst # [‘i’,’a’,’u’,’o’] – pops the item at 3rd index
[3, 2, 1]
1
[3, 2]
e
[‘i’, ‘a’, ‘u’, ‘o’]

lst=[3,2,1]
lst.sort() # sorts in ascending order for numbers
print lst # [1, 2, 3]
lst=[‘i’,’a’,’e’,’u’,’o’]
lst.sort() # sorts in alphabeting order for strings
print lst # [‘a’, ‘e’, ‘i’, ‘o’, ‘u’]
[1, 2, 3]
[‘a’, ‘e’, ‘i’, ‘o’, ‘u’]

lst[100] # trying to access an index not existing
IndexErrorTraceback (most recent call last)
<ipython-input-33-ee69601865a9> in <module>()
—-> 1 lst[100]
IndexError: list index out of range

exIhw

               

# creating a nested list – a list inside the other – list can have any dynamic size
matrixlist1=[10,20,30]
matrixlist2=[40,50,60,70]
matrixlist3=[80,90]

# adding the lists in another list
matrixlist = [matrixlist1,matrixlist2,matrixlist3]

#accessing the list by their indices
print matrixlist # [[10, 20, 30], [40, 50, 60, 70], [80, 90]]
print matrixlist[0] # [10, 20, 30]
print matrixlist[0][0] # 10
print matrixlist[0][1] # 20
print matrixlist[0][2] # 30

[[10, 20, 30], [40, 50, 60, 70], [80, 90]]
[10, 20, 30]
10
20
30

print matrixlist[1] # [40, 50, 60, 70]
print matrixlist[1][0] # 40
print matrixlist[1][1] # 50
print matrixlist[1][2] # 60
print matrixlist[1][2] # 70

[40, 50, 60, 70]
40
50
60
60

print matrixlist[2] # [80, 90]
print matrixlist[2][0] # 80
print matrixlist[2][1] # 90

[80, 90]
80
90

exIhw

                 

What are Dictionaries?

  • While String is an immutable sequences and lists are mutable sequences,
  • Dictionaries are actually mutable mappings,
  • Mappings are collection of objects stored as key value pairs.
In [64]:
# create an empty dictionary 
dict = {}
print dict
{}
In [18]:
# create a dictionary with key value pairs
dict = {'Name': 'Naeem', 'Age': 37 }
print dict
{'Age': 37, 'Name': 'Naeem'}
In [17]:
# access dictionary by key
print dict['Name']
Naeem
In [19]:
# access dictionary by key
print dict['Age']
37
In [20]:
# create a dictionary with key value pairs
dict = {'Name': 'Naeem', 'Age': 37, 'Address': {'Address1': '1 Austin St','City': 'Austin','State': 'TX', 'Zip': '78610',} }
print dict
{'Age': 37, 'Name': 'Naeem', 'Address': {'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'}}
In [21]:
# access dictionary by key
print dict['Address']
{'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'}
In [22]:
# access dictionary by nested keys
print dict['Address']['City']
Austin
In [24]:
# apply methods on the dictionary value
print dict['Address']['City'].upper()
AUSTIN
In [32]:
# creating dictionaries by assignment 
dict = {}
dict['Age'] = 37
dict['Name'] = 'Naeem'
dict['Address'] = {'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'}
print dict
{'Age': 37, 'Name': 'Naeem', 'Address': {'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'}}
In [26]:
# View the keys of the dictionary
dict.keys()
Out[26]:
['Age', 'Name', 'Address']
In [27]:
# View the values of the dictionary
dict.values()
Out[27]:
[37, 'Naeem', {'Address1': '1 Austin St', 'City': 'Austin', 'State': 'TX', 'Zip': '78610'}]
In [28]:
# View the items of the dictionary
dict.items()
Out[28]:
[('Age', 37), ('Name', 'Naeem'), ('Address', {'Address1': '1 Austin St', 'City': 'Austin', 'State': 'TX', 'Zip': '78610'})]
In [29]:
# clear a dictionary
dict.clear()
In [37]:
# View dictionary by methid dictionary.get(keyname)
print dict.get('Name')
Naeem
In [39]:
# pop items by key from dictionary
testpop ={"key1": "value1","key2": "value2","key3": "value3"}
print testpop
testpop.pop("key2")
print testpop
{'key3': 'value3', 'key2': 'value2', 'key1': 'value1'}
{'key3': 'value3', 'key1': 'value1'}
In [43]:
# update items by key in the dictionary
testupdate ={"key1": "value1","key2": "value2","key3": "value3"}
print testupdate
testupdate.update({"key2":"doublevalue2"})
print testupdate
{'key3': 'value3', 'key2': 'value2', 'key1': 'value1'}
{'key3': 'value3', 'key2': 'doublevalue2', 'key1': 'value1'}
In [53]:
# looping through a dictionary
for k,v in dict.items(): print 'Key: {0} Value: {1}'.format(k, v)
Key: Age Value: 37
Key: Name Value: Naeem
Key: Address Value: {'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'}
In [58]:
# looping through a dictionary
for item in dict.items(): print item
('Age', 37)
('Name', 'Naeem')
('Address', {'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'})
In [61]:
# looping through a dictionary keys, values, items
for item in dict.iterkeys(): print item
Age
Name
Address
In [62]:
# looping through a dictionary keys, values, items
for item in dict.itervalues(): print item
37
Naeem
{'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'}
In [63]:
# looping through a dictionary keys, values, items
for item in dict.iteritems(): print item
('Age', 37)
('Name', 'Naeem')
('Address', {'Address1': '1 Austin St', 'State': 'TX', 'Zip': '78610', 'City': 'Austin'})

 

What are tuples

  • Tuples are also like lists except that they are immutable
  • Once created can’t be updated
  • We use tuples very extensivly to ensure where the number of elements should be fixed and should not change.
  • E.g. Lets assume that we have a file storing movie name details – movieid, moviename, releasedate, netincome . If we want to export or import data to and fro from the file we would like to read or write to the file line by line. We can store each line info in a tuple.
# creating a tuple
testTuple = (1,2,3)
print testTuple
print testTuple[0]
(1, 2, 3)
1
# creating another tuple ( assuming that the fields are the lines of the movies file)
testTuple = (1001, "The Titanic", 1995, 7897967)
print testTuple
print testTuple[1]
(1001, 'The Titanic', 1995, 7897967)
The Titanic
# tuples are immutable ( can't update an element)
testTuple[0] = 9001
print testTuple
TypeErrorTraceback (most recent call last)
<ipython-input-7-952aa7d9dfd9> in <module>()
 1 # tuples are immutable
----> 2 testTuple[0] = 9001
 3 print testTuple TypeError: 'tuple' object does not support item assignment
# tuples are immutable ( can't add/insert an element)
print testTuple.append("Supe Hit")
AttributeErrorTraceback (most recent call last)
<ipython-input-8-d502cce852b2> in <module>()
----> 1 print testTuple.append("Supe Hit") AttributeError: 'tuple' object has no attribute 'append'
# only 2 methods supported - count and index - e.g. if you want to find the count of movies released in 1995
print testTuple.count(1995)
 1
# only 2 methods supported - count and index - e.g. the index of the release date 1995 is at index 2
print testTuple.index(1995)
 2

 

Files

  • Python support all file types.
  • For some basic files types the support is in-built for the others we need to install related modules
  • You can write files to the file system, read them, overrite them, delete them
Creating a File
%%writefile myfile.txt
This is line 1.
This is line 2.
This is line 3. 
Overwriting myfile.txt
# opening a file
myfile = open("myfile.txt")
# reading a file
myfile.read()
'This is line 1.\nThis is line 2.\nThis is line 3.'
# reading a file - but errrrrrrrrrrrrrr - why ??? because you reached end of file
myfile.read()
''
# reading a file - seek to the begining - as you raeached end of file file.read() returned blank so seek to begining of file
myfile.seek(0)
myfile.read() # read()returns the lines a string
'This is line 1.\nThis is line 2.\nThis is line 3.'
# reading a file - seek to the begining - as you raeached end of file file.read() returned blank so seek to begining of file
myfile.seek(0)
myfile.readlines() # readlines() returns the lines a string
['This is line 1.\n', 'This is line 2.\n', 'This is line 3.']
# reading a file - using for loop
for line in open("myfile.txt"): print line
This is line 1. This is line 2. This is line 3.

 

Sets and Booleans

  • Sets are unordered collection of unique objects.
  • Booleans are objects which return values True or False when an expression is evaluated.
# Creating a set - use set() method and .add(object) functions to add memebers to set
myset = set()
myset.add(3)
myset.add(1)
myset.add(2)
myset.add(3)
print myset 
set([1, 2, 3])
#converting a list into a set - use set(list) to convert a list into a set
mylist = [3,2,2,1,3,5,4,5,6,5]
myset = set(mylist)
print myset
set([1, 2, 3, 4, 5, 6])
# Booleans
booldata= True
print booldata
True
# Booleans
booldata= 5>7
print booldata 
False

 

Comparision Operators

  • Python supports all basic comparison operators as well as chained operators
  • Here is the list below:
  • == – equal to. e.g. 4 == 4 returns True, 4 == 5 returns False
i=4
j=4
k=5
l=3
print i==j
print i==k 
True
False
  • != – not equal to. e.g. 4 != 4 returns False, 4 != 5 returns True
print i!=j
print i!=k 
False
True
  • <> – not equal to. e.g. 4 <> 4 returns False, 4 <> 5 returns True
print i<>j
print i<>k 
False
True
    • greater than. e.g. 4 > 4 or 4 > 5 returns False, 4 > 3 returns True
print i>j
print i>k
print i>l
False
False
True
  • = – greater than equal to . e.g. 4 >= 5 returns False, 4 >= 4, 4 >= 3 returns True

print i>=j
print i>=k
print i>=l 
True
False
True
  • < – less than. e.g. 4 < 4 or 4 > 5 returns False, 4 < 3 returns True
print i<j
print i<k
print i<l 
False
True
False
  • <= – less than equal to . e.g. 4 <= 3 returns False, 4 <= 4, 4 <= 5 returns True
print i<=j
print i<=k
print i<=l 
True
True
False
  • chained comparision operator – operator applied one after the other
i=4
j=4
k=5
l=3
print i<k>l
print i<k and k>l 
True
True

 

If statements

  • Scenario 1 : evaluates the if condition only
# evaluates a simple if condition and if true perform the actions under if
i=10
j=10
if i==j: print "Equal" 
Equal
  • Scenario 2 : evaluates the if and then else conditions
# evaluates if condition and if true perform the actions 
# else performs actions under else.
if i>j: print "Greater" else: print "Equal" 
Equal
  • Scenario 3 : evaluates the if, elsif and else conditions
# evaluates if condition and if true perform the actions 
# other wise evaluates all the else ifs and performs actions under those 
# else ifs else performs actions under else.
if i>j: print "Greater" else if i<j: print "Less" else: print "Equal"
Equal

For loops

# iterates through the list
lst = range(1,11) # the range function is used to generate a range of values
for num in lst: print num
1
2
3
4
5
6
7
8
9
10
# iterates through the list
lst = range(1,11,2) # the range function is used to generate a range of values but see the step ...Syntax range(start, end, step)
for num in lst: print num
1
3
5
7
9
# iterates through the list also evaluates the numbers in the loop using if
lst = range(1,11) for num in lst: if(num%2 == 0): print num
2
4
6
8
10
# iterates through the multi dimensional tuple
mutilst = ((1,2,3),(4,5,6)) for x in mutilst: for y in x: print y
1
2
3
4
5
6
# iterates a dictionary
dict={'decimaldigits': {0,1,2,3,4,5,6,7,8,9}, 'binarydigits': {0,1}, 'hexadecimaldigits': {0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'}}
for item in dict.items(): print item
for key in dict.keys(): print key
for value in dict.values(): print value
for key, value in dict.items(): print key, value
('binarydigits', set([0, 1]))
('hexadecimaldigits', set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'f', 'c', 'b', 'a', 'e', 'd']))
('decimaldigits', set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
binarydigits
hexadecimaldigits
decimaldigits
set([0, 1])
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'f', 'c', 'b', 'a', 'e', 'd'])
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
binarydigits set([0, 1])
hexadecimaldigits set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'f', 'c', 'b', 'a', 'e', 'd'])
decimaldigits set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

While Loops

# while loop evaluates and condition and continues till condition fails
ctr = 0
while ctr <=10: print ctr ctr+=1 
0
1
2
3
4
5
6
7
8
9
# while loop evaluates and condition and continues till condition fails
# you can break at a condition ( says if ctr>==5)
ctr = 0
while ctr <=10: print ctr ctr+=1 if ctr>=6: break
0
1
2
3
4
5
# while loop evaluates and condition and continues till condition fails
# you can continue at a condition ( says if ctr is odd dont print)
ctr = 0
while ctr < 10: ctr+=1 if ctr==5: print 'Counter is 5 breaking' break if ctr%2!=0: print 'Counter is odd continuing' continue else: print ctr
Counter is odd continuing
2
Counter is odd continuing
4
Counter is 5 breaking

List Comprehensions

# list comprehensions are used to build objects
mylst = [x for x in "Mohd Naeem"]
print mylst 
['M', 'o', 'h', 'd', ' ', 'N', 'a', 'e', 'e', 'm']
# list comprehensions are used to build objects
# we are doing an action x*2 so the new set is 2,4,6
mylst = [x*2 for x in [1,2,3]]
print mylst
[2, 4, 6]
# list comprehensions are used to build objects
# we are doing an action x**.5 to get square root of the numbers 
mylst = [x**.5 for x in [1,2,3]]
print mylst
[1.0, 1.4142135623730951, 1.7320508075688772]
# list comprehensions are used to build objects
# we are doing an action x**2 to get square of the numbers 
mylst = [x**2 for x in [1,2,3]]
print mylst
[1, 4, 9]
# list comprehensions are used to build objects
# we are doing an action only print even
mylst = [x for x in range(1,21) if x%2==0]
print mylst
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

 

Methods, Functions, Lambda Expressions and Scope of variables/functions

Methods

  • functionality of object called to perform an action
  • Syntax : object.method(parmater1, parameter2…paramatern)
  • E.g – See the example below:
from __future__ import print_function strName = "Naeem"
print(strName.title())
print(strName.upper())
print(strName.lower())
Naeem
NAEEM
naeem

Functions

  • Functions are building blocks for reusablity of your code, you write functions to perform repeatitive functionality by writing it once and calling it again and again
  • We use def statement to define a statement : e.g def mysqrt(number)
  • Lets create our first function:
# defining a function using a print functionality inside the function
def MySquareRoot(num): print num**(1.0/2)
#using a function
MySquareRoot(5)
2.2360679775
# defining a function using a return statement inside the function
def MySquare(num): return num**2
#using a function
print(MySquare(3)) 
9
# defining a anonymous functions using a lambda expressions
def MyCalculator(action, num1, num2): if(action.lower() == "add"): return num1+num2 elif(action.lower() == "subtract"): return num1-num2 elif(action.lower() == "multiply"): return num1*num2 elif(action.lower() == "divide"): return num1/num2 else: return "Please mention correct action, number1 and number2"
#using a function
print(MyCalculator("add", 10, 5))
print(MyCalculator("subtract", 10, 5))
print(MyCalculator("multiply", 10, 5))
print(MyCalculator("divide", 10, 5))
print(MyCalculator("division", 10, 5))
15
5
50
2
Please mention correct action, number1 and number2

Lambda expressions

  • Lambda expressions are one line statements instead of a block to reference an argument and perform some action on it.
  • it helps us create anonymous functions
  • Syntax : function_name = lambda parameter : parameter action
# defining a anonymous functions using a lambda expressions
MyCube = lambda x : x**3
#using a lambda expressions function
print(MyCube(3))
27
# defining a anonymous functions using a lambda expressions
MyCubeRoot = lambda x : x**(1.0/3)
#using a lambda expressions function
print(MyCubeRoot(3)) 
1.44224957031
# defining a anonymous functions using a lambda expressions
MyAdd = lambda x,y : x+y
#using a lambda expressions function
print(MyAdd(3,5)) 
8
# defining a anonymous functions using a lambda expressions
MyRevString = lambda strToRev : strToRev[::-1]
#using a lambda expressions function
print(MyRevString("Naeem")) 
meeaN
# defining a anonymous functions using a lambda expressions
MyLambdaCalculator = lambda action, number1, number2 : number1+number2 if action.lower()=="add" else(number1-number2 if action.lower()=="subtract" else (number1*number2 if action.lower()=="multiply" else(number1/number2 if action.lower()=="divide" else "Please mention correct action, number1 and number2"))) #using a lambda expressions function
print(MyLambdaCalculator("add", 10, 5))
print(MyLambdaCalculator("subtract", 10, 5))
print(MyLambdaCalculator("multiply", 10, 5))
print(MyLambdaCalculator("divide", 10, 5))
print(MyLambdaCalculator("division", 10, 5))
15
5
50
2
Please mention correct action, number1 and number2

Scope of variables/functions

  • A Variable/Functions is Python is created with the following scopes:
  • Global – declare globally in a module or def file
  • Local – assigned within a function
  • Function Local – assigned within scope of a function ( within scope of a function inside a function)
  • Per-defined/Built-in – already defined like range, open …
MyCube = lambda x : x**3 #x is local
print(MyCube(3))
27
# all the 3 'i' variables have their own scope, so will print their own scope values
i=10 #global
def func1(): # print "Before setting new value of i in func1: %d" %(i) . This will be error, variable referenced before declaring i=20; #function local print( "After setting new value of i in func1: %d" %(i)) def func2(): # print "Before setting new value of i in func2: %d" %(i) . This will be error, variable referenced before declaring i=30 # local print()"After setting new value of i in func2: %d" %(i)) func2()
func1()
print(i)
After setting new value of i in func1: 20
After setting new value of i in func2: 30
10
# since variable is declared as global, it will accessed by func1, func2 as well as anywhere on this notebook
i=10 #global
def func1(): # print "Before setting new value of i in func1: %d" %(i) . This will be error, variable referenced before declaring #i=20; #function local print( "the value of i in func1: %d" %(i)) def func2(): # print "Before setting new value of i in func2: %d" %(i) . This will be error, variable referenced before declaring #i=30 # local print()"the value of i in func2: %d" %(i)) func2()
func1()
print(i)
the value of i in func1: 10
the value of i in func2: 10
10
# volume of sphere 
vol = lambda rad : 3.14*(rad**3)
print(vol(2)) 
25.12
#range check
def range_chk(number, low, high): exists=0 rng= range(low, high+1) for x in rng: if number ==x: exists=1 break else: continue if exists: print("Number exists") else: print("Number does not exists")
range_chk(5,1,10) range_chk(15,1,10)  
Number exists
Number does not exists
#counts lower and upper case characters in a sentance
def upper_lower(sentance): upperCnt=0 lowerCnt=0 for x in sentance: if x.isupper(): upperCnt=upperCnt+1 elif x.islower(): lowerCnt=lowerCnt+1 print("Count of upper cases: %d" %(upperCnt)) print("Count of lower cases: %d" %(lowerCnt))
upper_lower("Mohd Naeem")
Count of upper cases: 2
Count of lower cases: 7
#checks for palindrome 
pal = lambda s : s.replace(' ','') == s[::-1].replace(' ','')
print(pal('abcbac')) 
False
# returns less of the 2 if both numbers are even, other wise greater of the two, use lambda as well as min and max functions
lesser_if_two_evens_else_greater = lambda num1,num2 : min(num1,num2) if num1%2==0 and num2%2==0 else max(num1,num2)
print(lesser_if_two_evens_else_greater(2,4))
print(lesser_if_two_evens_else_greater(2,5)) 
2
5
# returns True if both words begin with same letter else false
same_letter_check = lambda word : word.split()[0][0]==word.split()[1][0]
print(same_letter_check("hi hawai"))
print(same_letter_check("hi pawai"))
True
False
# checks if any of the 2 numners is a twenty or sum of the numners is twenty
check_twenty = lambda num1, num2 : num1+num2==20 or num1==20 or num2==20
print(check_twenty(10,10))
print(check_twenty(20,10))
print(check_twenty(30,20))
print(check_twenty(20,20))
print(check_twenty(30,15))
True
True
True
True
False
#capitalizes the 1st and 4th charcter of a word
capitalize_wordpart = lambda word : word.replace(word[0],word[0].upper()).replace(word[3],word[3].upper())
print(capitalize_wordpart("jasmine"))
JasMine
# reverses each word in a sentance, uses split to split words, then reverses using [::-1] and then finally joins
#' '.join(word[::-1] for word in Sentence.split(" "))
reverse_words = lambda words : ' '.join(word[::-1] for word in words.split(" "))
print(reverse_words("This is your test")) 
sihT si ruoy tset
#checks if a number is within a range of 10 from either 100 or 200
almostthere = lambda num : (abs(num-100) <=10) or (abs(num-200) <=10) print(almostthere(108))
print(almostthere(205))
print(almostthere(92))
print(almostthere(250)) 
True
True
True
False
# checks a pattern 1,3
def pattern_check(numlist): for i in range(0, len(numlist)-1): if (numlist[i] == numlist[i+1]): return 1==1 return 1==2
print(pattern_check([1,3,3]))
print(pattern_check([1,3,1,3]))
True
False
# triplicates a character in a word
triplicate = lambda word :''.join((x*3 for x in word if x != ''))
print(triplicate("Mohammed"))
print(triplicate("Naeem"))
print(triplicate("Siddiqui")) 
MMMooohhhaaammmmmmeeeddd
NNNaaaeeeeeemmm
SSSiiiddddddiiiqqquuuiii
  • map function its applies a function on iterative list of items
# map function its applies a function on iterative list of items
mapperSquare = lambda num : num**2 # the square function
my_list =[1,2,3,4,5,6] # the list on which map function will apply square function
print(list(map(mapperSquare, my_list))) # finally returning a list of results
[4, 9, 16, 25, 36]
# map function its applies a function on iterative list of items
mapperSquareRoot = lambda num : num**(1.0/2) # the square root function
my_list =[1,2,3,4,5,6] # the list on which map function will apply square root function
print(list(map(mapperSquareRoot, my_list))) # finally returning a list of results
[1.0, 1.4142135623730951, 1.7320508075688772, 2.0, 2.23606797749979, 2.449489742783178]
  • filter functions applies a function on list of all iterbales but filters only those which return true
# filter function - just like map function applies a function to a list of iterables , 
# filter functions applies a function on list of all iterbales but filters only those which return true 
checkodds = lambda num : num%2<>0 # the odds function
mylist = range(0,51) # the list of iterables on which filter function will apply
print(list(filter(checkevens, mylist)))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]
  • args and kwargs parameters allow you to pass arbitrary numbers of arguments to a function
  • args allows you to pass those values as tuple
  • kwargs allows you to pass those values as dictionary
def sumanynumbers(*args): return sum(args)
print(sumanynumbers(10,20,30)) 
60
def checkoddeven(**kwargs): if 'Odd' in kwargs: print(kwargs['Odd']) else: print(kwargs['Even']) checkoddeven(Odd='15')
checkoddeven(Even='20')
15
20

 

My Own Tic Tac Toe: 1- Its prompts for how many matches you want to play in a series e.g. 3,5,7,9 2- Keeps a count on how many matches who won and who won the series 3- If a player wins the series before series ends e.g if you won first 2 matches of a series of 3 matches, then 3rd game is not played.

#!/usr/bin/python from __future__ import print_function
from IPython.display import clear_output
import random
import os def playagain(): return raw_input('Do you want to play again? Enter Yes or No:').lower().startswith('y') def howmanymatches(): countofmatches = 0 while countofmatches not in '3 5 7 9'.split(): countofmatches = raw_input('How many matches for the series, please enter your choice (3,5,7,9): ') return int(countofmatches) def tictactoe_board(board): clear_output() os.system('clear') print(' | |') print(' ' + board[7] + ' | ' + board[8] + ' | ' + board[9]) print(' | |') print('-----------') print(' | |') print(' ' + board[4] + ' | ' + board[5] + ' | ' + board[6]) print(' | |') print('-----------') print(' | |') print(' ' + board[1] + ' | ' + board[2] + ' | ' + board[3]) print(' | |') def whoplaysfirst(): if random.randint(0, 1) == 0: return 'Player 1' else: return 'Player 2' def playersmove(board): position = ' ' while position not in '1 2 3 4 5 6 7 8 9'.split() or not checkforSpace(board, int(position)): position = raw_input('Please enter your choice (1-9): ') return int(position) def checkforwin(board, mark): return ((board[7] == mark and board[8] == mark and board[9] == mark) or # across the top (board[4] == mark and board[5] == mark and board[6] == mark) or # across the middle (board[1] == mark and board[2] == mark and board[3] == mark) or # across the bottom (board[7] == mark and board[4] == mark and board[1] == mark) or # down the middle (board[8] == mark and board[5] == mark and board[2] == mark) or # down the middle (board[9] == mark and board[6] == mark and board[3] == mark) or # down the right side (board[7] == mark and board[5] == mark and board[3] == mark) or # diagonal (board[9] == mark and board[5] == mark and board[1] == mark)) # diagonal def checkforSpace(board, position): return board[position] == ' ' def checkforboardfull(board): for i in range(1,10): if checkforSpace(board, i): return False return True
def playerXor0(): marker = '' while not (marker == 'X' or marker == '0'): marker = raw_input('Player 1, Please enter if you want to be X or 0 : ').upper() if marker == 'X': return ('X', 'O') else: return ('O', 'X') def placemarker(board, marker, position): board[position] = marker seriesmatches = howmanymatches()
onwinvalue = 10
player1WinCount = 0
player2WinCount = 0
startseries = 0
print('Welcome to my Tic Tac Toe!!!')
startseries = 0
while True: startseries = startseries + 1 print ("Match %d of %d" %(startseries, seriesmatches)) myboard = [' '] * 10 player1marker, player2marker = playerXor0() game_on = True turn = whoplaysfirst() while game_on: if turn == 'Player 1': tictactoe_board(myboard) pos= playersmove(myboard) placemarker(myboard, player1marker, pos) if checkforwin(myboard, player1marker): tictactoe_board(myboard) print('Player 1 wins...') player1WinCount = player1WinCount + 1 game_on = False else: if checkforboardfull(myboard): tictactoe_board(myboard) print('It is a draw...') break else: turn = 'Player 2' else: tictactoe_board(myboard) pos= playersmove(myboard) print(player1marker) print(pos) placemarker(myboard, player2marker, pos) if checkforwin(myboard, player2marker): tictactoe_board(myboard) print('Player 2 wins...') player2WinCount = player2WinCount + 1 game_on = False else: if(checkforboardfull(myboard)): tictactoe_board(myboard) print('It is a draw...') break else: turn = 'Player 1' if startseries == seriesmatches or (float(player1WinCount)/seriesmatches > .5) or (float(player2WinCount)/seriesmatches > .5): break; print ("Player 1 win count - %d and score - %d" %(player1WinCount, player1WinCount*onwinvalue))
print ("Player 2 win count - %d and score - %d" %(player2WinCount, player2WinCount*onwinvalue)) if (float(player1WinCount)/seriesmatches > .5): print ("Player 1 wins the series %d - %d" %(player1WinCount, player2WinCount))
elif (float(player2WinCount)/seriesmatches > .5): print ("Player 2 wins the series %d - %d" %(player2WinCount, player1WinCount))
else: print ("The series was drawn") 
 | | O | | | |
----------- | | X | O | X | |
----------- | | O | X | O | |
Player 1 wins...
Player 1 win count - 2 and score - 20
Player 2 win count - 0 and score - 0
Player 1 wins the series 2 - 0

  Python Part 3 of 5:

Object Oriented Programming

  • Everything in Python is an object
# i is of int type object
i=10
type(i)
int
# i is of str type object
i="Naeem"
type(i)
str
# i is of list type object
i=[1,2,3]
type(i)
list
# i is of tuple type object
i=(1,2,3)
type(i)
tuple
# i is of dict type object
i={"key1": "value"}
type(i)
dict
# sqrt is of function type object
def sqrt(num): return num **(1.0/2)
type(sqrt)
function
  • So how to create out own objects, we use class
  • class is blue print of a behavior
  • object is a instance of a class
  • a class has attributes and methods.
  • attributes are the characteristics of a class
  • methods are the operations performed by the class
# create your 1st class, MyHelloWorldObject is an object of type MyHelloWorldClass
class MyHelloWorldClass(object): pass
myHelloWorldObject = MyHelloWorldClass()
type(myHelloWorldObject)
__main__.MyHelloWorldClass
# create a Student class with special method __init__ 
class Student(object): def __init__(self,name): self.name=name
objStud1 = Student(name="Naeem") print objStud1.name
objStud2 = Student(name= "Naeem2") print objStud2.name
Naeem
Naeem2
# create a Student class with special method __init__ with a class attribute grade
class Student(object): grade = 10 def __init__(self,name, age): self.name=name self.age=age
objStud1 = Student(name="Naeem", age=39) print objStud1.name
print objStud1.age
print objStud1.grade
objStud2 = Student(name= "Naeem2", age=37) print objStud2.name
print objStud2.age
print objStud2.grade
Naeem
39
10
Naeem2
37
10
* __init__ - intializes a object
* __str__ - returns a string representation of the object
* __len__ - returns the length of the object
* __del__ - destroys the object
# create a Student class with special method __init__, __str__, __len__ and __del__
class Student(object): def __init__(self,name,age): self.name=name self.age=age def __str__(self): return "Name: %s and Age: %d" %(self.name,self.age) def __len__(self): return self.age def __del__(self): print "Student deleted" objStud1 = Student(name="Naeem", age=35) print objStud1
print len(objStud1)
del objStud1
Name: Naeem and Age: 35
35
Student deleted
# inheritance in classes - # the parent or base class it has a area method
class Figure(object): length=0 width=0 def __init__(self, length, width): self.length=length self.width=width def area(self): return self.length * self.width objFigure = Figure(length=5, width=7)
print (objFigure.area())
35
# Rectangle child class of class Figure ....its has perimter method of its own, inherits the area method from parent
class Rectangle(Figure): def __init__(self, length, width): Figure.__init__(self, length, width) def perimeter(self): return (2*self.length) * (2*self.width) objFigure = Rectangle(length=5, width=7)
print(objFigure.area())
print(objFigure.perimeter())
35
140
# Sphere child class of class Figure ....its has volume method of its own, inherits the area method from parent
class Cube(Figure): height =0 def __init__(self, length, width, height): Figure.__init__(self, length, width) self.height=height def volume(self): return self.length * self.width * self.height objFigure = Cube(length=5, width=7, height=9)
print(objFigure.area())
print(objFigure.volume())
35
315
# instantiating a circle class with with all special methods
# __init__- intializes an object
# __str__ - returns the string representation of an onject
# __len__ - returns the length/count as the case may be
# __del__ - deletes an object
class Circle(object): pi = 3.14 def __init__(self, rad=1): # default value for a parameter, if no radiius passed will return default of 1 self.rad=rad def __str__(self): return "Circle String representation raduis:%s" %str(self.rad) def __len__(self): return self.rad def setCircle(self, rad=1): self.rad=rad def getArea(self): print("Circle area(raduis):%s" %str(self.pi*(self.rad)**2)) def getPerimeter(self): print("Circle perimiter(raduis):%s" %str(2*self.pi*self.rad)) def __del__(self): print("Circle deleted") objCircle = Circle() # not raduis passed will take dafault value of 1
print(objCircle)
print("Length or raduis of circle %d:" %(len(objCircle)))
objCircle.getArea()
objCircle.getPerimeter()
del objCircle objCircle = Circle(5) # not raduis passed will take dafault value of 1
print(objCircle)
print("Length or raduis of circle %d:" %(len(objCircle)))
objCircle.getArea()
objCircle.getPerimeter()
del objCircle
Circle deleted
Circle String representation raduis:1
Length or raduis of circle 1:
Circle area(raduis):3.14
Circle perimiter(raduis):6.28
Circle deleted
Circle String representation raduis:5
Length or raduis of circle 5:
Circle area(raduis):78.5
Circle perimiter(raduis):31.400000000000002
Circle deleted
# create a class Line and pass the coordinates of the line aspair of tuples
# Calculate the distance and slope based on the passed coordinates
class Line(object): def __init__(self, point1, point2): self.point1=point1 self.point2=point2 def distance(self): x1,y1= self.point1 x2,y2= self.point2 return ((x2-x1)**2 + (y2-y1)**2)**0.5 def slope(self): x1,y1= self.point1 x2,y2= self.point2 return (y2-y1)/(x2-x1) point1= (2,4)
point2= (5,11)
objLine = Line(point1, point2)
print(objLine.distance())
print(objLine.slope())
7.615773105863909
2.3333333333333335
# create a class Cylinder which takes raduis and height 
# and returns the volume (πr2h) and surface area (2πr2 + 2πrh)
class Cylinder(object): pi = 3.14 def __init__(self, rad=1, height=1): self.rad=rad self.height=height def volume(self): return ((self.pi)*((self.rad)**2)*self.height) def surfacearea(self): return ((2*(self.pi)*(self.rad**2)) + (2*(self.pi)*self.rad*self.height)) objCylinder = Cylinder()
print(objCylinder.volume())
print(objCylinder.surfacearea()) objCylinder = Cylinder(2,3)
print(objCylinder.volume())
print(objCylinder.surfacearea())
3.14
12.56
37.68
62.8
# create a bank account class that has two attributes: owner, balance
# and two methods: deposit, withdraw
# As an added requirement, withdrawals may not exceed the available balance.
class Account(object): def __init__(self, owner="Test", balance=0): self.owner=owner self.balance=balance def __str__(self): return "Account owner: %s, Account balance: %d" %(str(self.owner), int(self.balance)) def deposit(self, amounttodeposit): self.balance = self.balance + amounttodeposit print("%s, %d is successfully deposited to you account, your new balance is: %d." %(self.owner, int(amounttodeposit), int(self.balance))) def withdraw(self, amounttowithdraw): if(self.balance>=amounttowithdraw): self.balance = self.balance - amounttowithdraw print("%s, %d is successfully withdrawn you account, your new balance is: %d." %(self.owner, int(amounttowithdraw), int(self.balance))) else: print("%s, your balance is %d, you can't withdraw %d." %(self.owner, int(self.balance), int(amounttowithdraw)))
objAccount = Account("Naeem", 100)
print(objAccount)
objAccount.deposit(500)
objAccount.deposit(750)
objAccount.withdraw(1000)
objAccount.withdraw(500)
objAccount.withdraw(300) 
Account owner: Naeem, Account balance: 100
Naeem, 500 is successfully deposited to you account, your new balance is: 600.
Naeem, 750 is successfully deposited to you account, your new balance is: 1350.
Naeem, 1000 is successfully withdrawn you account, your new balance is: 350.
Naeem, your balance is 350, you can't withdraw 500.
Naeem, 300 is successfully withdrawn you account, your new balance is: 50.

 

Exception/Error handling in Python

  • When ever there is an error situation in the code.
  • It throws an exception and the execution of the script stops there.
  • Which means if error and exception scenarios are not handled properly our code will never execute completely.
  • Puthon provides the following way to handle such situations
    • try – its the block where you will put yr error prone code
    • except – its the block where you will handle the error, you can have as many except blocks based on the Error Types
    • else – its the block where you will handle what to do if exception does not occur
    • finally – its the block where you will handle any stuff whih must always be executed no matter exception occurs or not
# a try, except, else and finally block handling any kind of error situation
def divideme(num1, num2): try: result = num1/num2 except ZeroDivisionError: print "You cant divide by zero" except: print "You got an error but you handled it." else: print result finally: print "I always execute" divideme(6,2)
print "------------"
divideme(6,0)
print "------------"
divideme(6,"1")
3
I always execute
------------
You cant divide by zero
I always execute
------------
You got an error but you handled it.
I always execute
# a try, except, else and finally block handling any kind of error situation with looping till correct values past
def divideme(num1): while True: try: num2= int(input("Please input a number: ")) result = num1/num2 except ZeroDivisionError: print "You cant divide by zero" continue except: print "You got an error but you handled it." continue else: print result break finally: print "I always execute" divideme(6) 
Please input a number: one
You got an error but you handled it.
I always execute
Please input a number: 0
You cant divide by zero
I always execute
Please input a number: 2
3
I always execute
# handling TypeError 
for i in ['x','y','z']: try: print(i**(1.0/2)) except: print "Please ensure its a number"
Please ensure its a number
Please ensure its a number
Please ensure its a number

 

Code Review and Unit Testing in Python for better code

  • It is not only a good practise to use exception hadling but also use tool for analysing your code and unit test your code
  • Python supports many tools for code review and analaysis – pylintpiflakes etc
  • Python also supports tools for Unit testing your code – unittestdoctest etc.

pylint – for code review

# in Jupyter Notebook use ! pip install pylint, 
# in windows command prompt, mac/Linux terminal use - pip install pylint
! pip install pylint
Requirement already satisfied: pylint in c:\programdata\anaconda2\lib\site-packages
Requirement already satisfied: astroid>=1.5.1 in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: six in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: isort>=4.2.5 in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: mccabe in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: singledispatch in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: configparser in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: backports.functools_lru_cache in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: colorama in c:\programdata\anaconda2\lib\site-packages (from pylint)
Requirement already satisfied: lazy_object_proxy in c:\programdata\anaconda2\lib\site-packages (from astroid>=1.5.1->pylint)
Requirement already satisfied: wrapt in c:\programdata\anaconda2\lib\site-packages (from astroid>=1.5.1->pylint)
Requirement already satisfied: enum34>=1.1.3 in c:\programdata\anaconda2\lib\site-packages (from astroid>=1.5.1->pylint)
%%writefile test.py
x = 10
y = 20
z = 30
print x
print y
print Z
# in Jupyter Notebook, you can add line to a file as above # in windows command prompt, mac/Linux terminal use nano test.py
Overwriting test.py
# in Jupyter Notebook use ! pylint test.py, 
# in windows command prompt, mac/Linux terminal use - pylint test.py
! pylint test.py
************* Module test
C: 7, 0: Trailing whitespace (trailing-whitespace)
C: 8, 0: Final newline missing (missing-final-newline)
C: 1, 0: Missing module docstring (missing-docstring)
C: 1, 0: Invalid constant name "x" (invalid-name)
C: 2, 0: Invalid constant name "y" (invalid-name)
C: 3, 0: Invalid constant name "z" (invalid-name)
E: 6, 6: Undefined variable 'Z' (undefined-variable) -------------------------------------------------------------------- Your code has been rated at -8.33/10 (previous run: 1.67/10, -10.00)
No config file found, using default configuration
%%writefile test.py
"""
script to add numbers
""" def myadd(): """ add function. """ firstnumber = 10 secondnumber = 20 print firstnumber print secondnumber myadd()
Overwriting test.py
# lets test again
! pylint test.py
************* Module test
C: 14, 0: Final newline missing (missing-final-newline) ------------------------------------------------------------------ Your code has been rated at 8.33/10 (previous run: 5.00/10, +3.33)
No config file found, using default configuration

unittest for unit testing code

%%writefile myCaps.py
def makeCaps(word): return word.capitalize()
# lets create a function in a file testCaps.py --- Take 1 
Overwriting myCaps.py
%%writefile testMyCaps.py
import unittest
import myCaps class TestCap(unittest.TestCase): def test_one_word(self): word = 'naeem' result = myCaps.makeCaps(word) self.assertEqual(result, 'Naeem') def test_multiple_words(self): word = 'mohd naeem' result = myCaps.makeCaps(word) self.assertEqual(result, 'Mohd Naeem') if __name__ == '__main__': unittest.main()
# The test class testing again 2 test cases
Overwriting testMyCaps.py
# Now lets run the unit test
# the test failed because capitalize function cant only capitalize the first word of a sentance 
! python testMyCaps.py
F.
======================================================================
FAIL: test_multiple_words (__main__.TestCap)
----------------------------------------------------------------------
Traceback (most recent call last): File "testMyCaps.py", line 14, in test_multiple_words self.assertEqual(result, 'Mohd Naeem')
AssertionError: 'Mohd naeem' != 'Mohd Naeem' ----------------------------------------------------------------------
Ran 2 tests in 0.000s FAILED (failures=1)
%%writefile myCaps.py
def makeCaps(word): return word.title()
# lets modify a function in a file testCaps.py --- Take 2
Overwriting myCaps.py
# lets test again
# Hurray the results passed
! python testMyCaps.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s OK
%%writefile testMyCaps.py
import unittest
import myCaps class TestCap(unittest.TestCase): def test_one_word(self): word = 'naeem' result = myCaps.makeCaps(word) self.assertEqual(result, 'Naeem') self.assertNotEqual(result, word) def test_multiple_words(self): word = 'mohd naeem' result = myCaps.makeCaps(word) self.assertEqual(result, 'Mohd Naeem') self.assertNotEqual(result, word) def test_apos_words(self): word = "mohd naeem's blogs" result = myCaps.makeCaps(word) self.assertEqual(result, "Mohd Naeem's Blogs") self.assertNotEqual(result, word) if __name__ == '__main__': unittest.main()
# Now adding one more test case to test apostrophes
Overwriting testMyCaps.py
# lets test again
# Ohhh!!! 3rd testcase failed as its capitalized 'S
! python testMyCaps.py
F..
======================================================================
FAIL: test_apos_words (__main__.TestCap)
----------------------------------------------------------------------
Traceback (most recent call last): File "testMyCaps.py", line 19, in test_apos_words self.assertEqual(result, "mohd naeem's blogs")
AssertionError: "Mohd Naeem'S Blogs" != "mohd naeem's blogs" ----------------------------------------------------------------------
Ran 3 tests in 0.001s

FAILED (failures=1)
%%writefile myCaps.py
from string import capwords
def makeCaps(word): return capwords(word.title())
# lets modify a function in a file testCaps.py --- Take 3
Overwriting myCaps.py
# lets test again
# Hurray all the 3 testcases passed
! python testMyCaps.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s OK

 

Modules and Packages in Python

  • Modules are .py files consisting of functions, statements whihc can be imported into another file using import statement
  • Packages are third party python packages which can be installed using pip install

Modules:

 Predefined modules:
#importing a pre-defined module
import math
#using the module methods/functions
print math.floor(6.9)
6.0
#using the module methods/functions
print math.ceil(6.56)
7.0
#using the module methods/functions
print math.factorial(4)
24
Custom created modules:
%%writefile NaeemUtils.py def mysqr(num): return num**2
def mysqrt(num): return num**(1.0/2)
def mycube(num): return num**3
def mycubert(num): return num**(1.0/3)
# NaeemUtils become a module
# creating your own modules
Writing NaeemUtils.py
# importing NaeemUtils
import NaeemUtils
# calling NaeemUtils mysqr function
print NaeemUtils.mysqr(5) 
25
# calling NaeemUtils mysqrt function
print NaeemUtils.mysqrt(5)
2.2360679775

Packages

Predefined packages:
#to install packages, use pip install
!pip install colorama
Requirement already satisfied: colorama in c:\programdata\anaconda2\lib\site-packages
# to import packages, use from packagename import modulename
# here we are importing init module
from colorama import init
# here we are initializing init module
init()
# from colorama importing Fore, Back modules
from __future__ import print_function
from colorama import Fore, Back, Style
print(Fore.RED + 'Mohd Naeem, my name has red text')
print(Back.GREEN + 'and has a green background')
print(Style.RESET_ALL)
print('Now Everything is normal')
 Capture
Custom created packages:
!mkdir NaeemRootPackage
!mkdir NaeemRootPackage\NaeemMathPackage
# create a folder NaeemRootPackage and another subfolder NaeemMathPackage under it
%%writefile NaeemRootPackage\__init__.py
#create a file NaeemRootPackage\__init__.py . Python will treat NaeemRootPackage as a package due to the file __init__.py
Writing NaeemRootPackage\__init__.py
%%writefile NaeemRootPackage\Rootfunctions.py
def mycapitalize(text): return text.capitalize()
def mytitle(text): return text.title()
#create a file NaeemRootPackage\Rootfunctions.py
Writing NaeemRootPackage\Rootfunctions.py
%%writefile NaeemRootPackage\NaeemMathPackage\__init__.py
#create a file NaeemRootPackage\NaeemMathPackage\__init__.py . #Python will treat NaeemMathPackage as a package due to the file __init__.py
Writing NaeemRootPackage\NaeemMathPackage\__init__.py
%%writefile NaeemRootPackage\NaeemMathPackage\Mathfunctions.py
def mysqr(num): return num**2
def mysqrt(num): return num**(1.0/2)
def mycube(num): return num**3
def mycubert(num): return num**(1.0/3)
#create a file NaeemRootPackage\NaeemMathPackage\Rootfunctions.py
Writing NaeemRootPackage\NaeemMathPackage\Mathfunctions.py
#Lets import from NaeemRootPackage
from NaeemRootPackage import Rootfunctions

print(Rootfunctions.mycapitalize("mohd naeem"))
print(Rootfunctions.mytitle("mohd naeem"))

#Lets import from NaeemRootPackage.NaeemMathPackage
from NaeemRootPackage.NaeemMathPackage import Mathfunctions

print(Mathfunctions.mycube(3))
print(Mathfunctions.mycubert(27))
Mohd naeem
Mohd Naeem
27
3.0

 

The Black Jack game

Download from here and run as python BlackJack.py

#!/usr/bin/Python
# My Blackjack Game - Simple version
# import statements 
from __future__ import print_function
from IPython.display import clear_output
import random
import os #global variables
suits = ('Hearts','Diamonds','Spades','Clubs')
ranks = ('Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace')
values = {'Two':2,'Three':3,'Four':4,'Five':5,'Six':6,'Seven':7,'Eight':8,'Nine':9,'Ten':10,'Jack':10,'Queen':10,'King':10,'Ace':11}
playing = True # card classs
class Card: def __init__(self, suit, rank): self.suit=suit self.rank=rank def __str__(self): return ("%s of %s" %(self.rank, self.suit)) # deck class
class Deck: def __init__(self): self.deck=[] for suit in suits: for rank in ranks: self.deck.append(Card(suit,rank)) def __str__(self): deck_comp = '' for card in self.deck: deck_comp += "\n " + card.__str__() return deck_comp def shuffle(self): random.shuffle(self.deck) def deal(self): single_card = self.deck.pop() return single_card # Hand Class
class Hand: def __init__(self): self.cards=[] self.value=0 self.aces=0 def addCard(self, card): self.cards.append(card) self.value += values[card.rank] def adjustForAce(self): while self.value > 21 and self.aces: self.value -= 10 self.aces -= 1 # Chips Class
class Chips: def __init__(self): self.total=150 self.bet=0 def winBet(self): self.total += self.bet def looseBet(self): self.total -= self.bet # utility functions
def startbet(chips): while True: try: chips.bet = int(input("How many chips do you want to bet?")) except ValueError: print("Sorry!!!!, Please enter a number for bet.") else: if(chips.bet> chips.total): print("Sorry!!!, Please enter the bet value less than your total.") else: break; def hit(deck, hand): hand.addCard(deck.deal()) hand.adjustForAce() def hitorStand(deck,hand): global playing while True: x = int(input("Would you like to Hit or Stand? Enter '0' for hit, '1' for stand ")) if x == 0: hit(deck,hand) elif x == 1: print("Player stands. Dealer is playing.") playing = False else: print("Sorry, please try again.") continue break def ShowCardsNow(player, dealer): print("\nDealer's Hand:") print(" <card hidden>") print('',dealer.cards[1]) print("\nPlayer's Hand:", *player.cards, sep='\n ') def ShowCardsFinally(player, dealer): print("\nDealer's Hand:", *dealer.cards, sep='\n ') print("Dealer's Hand =",dealer.value) print("\nPlayer's Hand:", *player.cards, sep='\n ') print("Player's Hand =",player.value) def playerBusts(player,dealer,chips): print("Player busts!") chips.looseBet() def playerWins(player,dealer,chips): print("Player wins!") chips.winBet() def dealerBusts(player,dealer,chips): print("Dealer busts!") chips.winBet() def dealerWins(player,dealer,chips): print("Dealer wins!") chips.looseBet() def push(player,dealer,chips): print("It's a push!, player and dealer tie.") # game logic while True: # Print an opening statement print('This is a simple version of BlackJack Game! Get as close to 21 as you can without going over!\n\
 Dealer hits until she reaches 17. Aces count as 1 or 11.') # Create & shuffle the deck, deal two cards to each player deck = Deck() deck.shuffle() playerHand = Hand() playerHand.addCard(deck.deal()) playerHand.addCard(deck.deal()) dealerHand = Hand() dealerHand.addCard(deck.deal()) dealerHand.addCard(deck.deal()) # Set up the Player's chips playerChips = Chips() # default value 100 # Prompt the Player for their bet startbet(playerChips) # Show cards (but keep one dealer card hidden) ShowCardsNow(playerHand, dealerHand) while playing: # Prompt for Player to Hit or Stand hitorStand(deck, playerHand) # Show cards (but keep one dealer card hidden) ShowCardsNow(playerHand, dealerHand) # If player's hand exceeds 21, run playerBusts() and break out of loop if playerHand.value > 21: playerBusts(playerHand, dealerHand, playerChips) break; # If Player hasn't busted, play Dealer's hand until Dealer reaches 17  if playerHand.value <= 21: while dealerHand.value < 17: hit(deck, dealerHand) # Show all cards ShowCardsFinally(playerHand, dealerHand) # Run different winning scenarios if dealerHand.value > 21: dealerBusts(playerHand,dealerHand,playerChips) elif dealerHand.value > playerHand.value: dealerWins(playerHand,dealerHand,playerChips) elif dealerHand.value < playerHand.value: playerWins(playerHand,dealerHand,playerChips) else: push(playerHand,dealerHand,playerChips) # Inform Player of their chips total  print("\nPlayer's winnings stand at",playerChips.total) # Ask to play again new_game = int(input("Would you like to play another hand? Enter '0' for yes '1' for no.")) if new_game == 0: playing=True continue else: print("Thanks for playing!") break
 
This is simple version of Black Jack game! Get as close to 21 as you can without going over! Dealer hits until she reaches 17. Aces count as 1 or 11.
How many chips do you want to bet?50 Dealer's Hand: <card hidden> Eight of Hearts Player's Hand: Five of Spades Nine of Spades
Would you like to Hit or Stand? Enter '0' for hit, '1' for stand 0 Dealer's Hand: <card hidden> Eight of Hearts Player's Hand: Five of Spades Nine of Spades Seven of Diamonds
Would you like to Hit or Stand? Enter '0' for hit, '1' for stand 1
Player stands. Dealer is playing. Dealer's Hand: <card hidden> Eight of Hearts Player's Hand: Five of Spades Nine of Spades Seven of Diamonds Dealer's Hand: Four of Hearts Eight of Hearts Ace of Clubs
Dealer's Hand = 23 Player's Hand: Five of Spades Nine of Spades Seven of Diamonds
Player's Hand = 21
Dealer busts! Player's winnings stand at 200
Would you like to play another hand? Enter '0' for yes '1' for no.0
Welcome to BlackJack! Get as close to 21 as you can without going over! Dealer hits until she reaches 17. Aces count as 1 or 11.
How many chips do you want to bet?50 Dealer's Hand: <card hidden> Three of Diamonds Player's Hand: Five of Clubs Five of Hearts
Would you like to Hit or Stand? Enter '0' for hit, '1' for stand 0 Dealer's Hand: <card hidden> Three of Diamonds Player's Hand: Five of Clubs Five of Hearts King of Diamonds
Would you like to Hit or Stand? Enter '0' for hit, '1' for stand 1
Player stands. Dealer is playing. Dealer's Hand: <card hidden> Three of Diamonds Player's Hand: Five of Clubs Five of Hearts King of Diamonds Dealer's Hand: Ten of Clubs Three of Diamonds Jack of Diamonds
Dealer's Hand = 23 Player's Hand: Five of Clubs Five of Hearts King of Diamonds
Player's Hand = 20
Dealer busts! Player's winnings stand at 200

Python – Part 4 of 5 – Under construction

Decorators

  • They are used to “decorate” another function
  • “Decorate” means modify the bahavior of a function
  • The concept of decorators works on the following things:
    • calling one fucntion from inside another function
    • returning a function from inside another function
    • The swtich @ to handle decoration
  • How to call one function from inside another fuction
    • Here is the inner_func() defined inside outer_func()
    • since the scope of this function is within the outer_func()
    • we can call inner_func() from within outer_func()
# lets test how to call one function from inside another
def outer_func(): print "I am outer function" # here is the inner_func() defined inside outer_func() # since the scope of this function is within the outer_func() # we can call inner_func() from within outer_func() def inner_func(): print "I am inner function" # call inner_func() from within outer_func() inner_func()
# Lets call outer_func(), you can see that the inner_func got called from outer_func()
outer_func()
I am outer function
I am inner function
  • How to call one function from outside another
    • To make any inner function to be called from outside the outer function,
    • the outer fucntion MUST return the inner function
    • and then you can assign this function to a new function
# what if we want to call inner_func() from outside outer_func()
def outer_func(): print "I am outer function" # To make any inner function to be called from outside the outer function # the outer fucntion MUST return the inner function # and then you can assign this function to a new function def inner_func(): print "I am inner function" # call inner_func() from within outer_func() return inner_func
# We are assigning one function to the other 
test_inner_func = outer_func()
test_inner_func()
I am outer function
I am inner function
  • How to call a function as an urgument to the other function
def func1(): print "I am func1."
# func_as_argument is an function as argument
def func2(func_as_argument): print "I am calling another function" func_as_argument() # func_as_argument called # now pass a function as an argument to another function
func2(func1)
I am calling another function
I am func1.
  • How to create a decorator
# first lets have a function which we need to decorate/modify
def old_func(): print "I am old_func."
old_func()
I am old_func.
# now lets create our new function which will call old function as an argument
def new_func(func_argument): def wrapper_func(): print "I am new_func and here is some code executed before calling the other function as argument" func_argument() print "I am new_func and here is some code executed after calling the other function as argument" return wrapper_func
# now lets try old-func as an argument to new_func
# you can see that we are not only able to execute 
# - the new functionality of new_func but also the old_func too # first lets call old_func()
old_func() # now lets call decorator
test_wrapper_func = new_func(old_func)
test_wrapper_func()
I am old_func.
I am new_func and here is some code executed before calling the other function as argument
I am old_func.
I am new_func and here is some code executed after calling the other function as argument
# Now lets use the @ on off switchswitch
# If this @new_func switch is on , then it will call new as well as old functionality both
@new_func
def old_func(): print "I am old_func."
old_func()
I am new_func and here is some code executed before calling the other function as argument
I am old_func.
I am new_func and here is some code executed after calling the other function as argument
# If this @new_func switch is off/commented , then it will call new as well as old functionality both
#@new_func
def old_func(): print "I am old_func."
old_func() 
I am old_func.

 

Generators

  • Generators are used to generate a sequence to be consumed as and when needed
  • instead of ‘return’ we use ‘yield’
  • Example without a generator
    • list is holding the data in memory
    • imagine if we needed to generate a big sequence
# Example without a generator
def my_squares(n): # list is holding the data in memory,  # imagine if we needed to generate a big sequence result =[] for num in range(n): sqr = num **2 result.append(sqr) return result
my_squares(5)
[0, 1, 4, 9, 16]
  • Example with a generator
    • no list is holding the data in memory
    • value is consumed as needed
    • more efficient
# Example with a generator
def generate_squares(n): # no list is holding the data in memory,  # value is consumed as needed # more efficient for num in range(n): yield num **2
# Now lets see what happens when we execute the function
# its does not print the list of numbers squared
# it justtells that it is a genarator object
generate_squares(5)
<generator object generate_squares at 0x7fdc547c1a40>
#Now lets consume it
# you can see that the geenator generates the next number as needed
for num in generate_squares(5): print(num)
0
1
4
9
16
# you can cast a generator into a list
# it now genrates the list if e need a list
list(generate_squares(5))
[0, 1, 4, 9, 16]
  • Built-in Genarator functions
    • range()
    • filter()
    • map()
#Example of range genarator function
for num in range(5): print(num)
0
1
2
3
4
  • iter and next functions
    • They help to generate the next number in sequence
# using next()
gen_num =generate_squares(5)
# next function generates the next in the sequence number
print(next(gen_num))
0
# next function generates the next in the sequence number
print(next(gen_num))
1
# next function generates the next in the sequence number
print(next(gen_num))
4
# using Iter, we are creating an iterator for the list
l = range(11)
iter_vals = iter(l)
print(next(iter_vals))
print(next(iter_vals))
print(next(iter_vals))
print(next(iter_vals)) 
0
1
2
3

Python – Part 5 of 5

Advanced Collection modules

* Python supports the following collection modules - Counter - defaultdict - OrderedDict - namedTuple
  • Counter
    • it is a dict sublass to count hashtable objects
# lets import Counter disct subclass from collections module
from collections import Counter
from __future__ import print_function
# Counter with alphabets - create a Counter for a string to count the number of occurance of alphabets in a sentance/word
ctrAlphabets =Counter("the quick brown fox jumps over the lazy dog.")
print(ctrAlphabets) 
Counter({' ': 8, 'o': 4, 'e': 3, 'h': 2, 'r': 2, 'u': 2, 't': 2, '.': 1, 'a': 1, 'c': 1, 'b': 1, 'd': 1, 'g': 1, 'f': 1, 'i': 1, 'k': 1, 'j': 1, 'm': 1, 'l': 1, 'n': 1, 'q': 1, 'p': 1, 's': 1, 'w': 1, 'v': 1, 'y': 1, 'x': 1, 'z': 1})
# Counter with words - create a Counter for a string to count the number of occurance of words in a sentance/word
ctrWords =Counter("the quick brown fox jumps over the lazy dog.".split(' '))
print(ctrWords)
Counter({'the': 2, 'dog.': 1, 'brown': 1, 'lazy': 1, 'over': 1, 'fox': 1, 'quick': 1, 'jumps': 1})
# Counter with list of numbers - create a Counter with list of numbers
ctrLists =Counter([1,2,3,4,2,3,1,4,5,1,7,3,6,8,2,9,8,4,7,1,9,2,8,3,7,3,7,4, 5,6])
print(ctrLists) 
Counter({3: 5, 1: 4, 2: 4, 4: 4, 7: 4, 8: 3, 5: 2, 6: 2, 9: 2})
# convert a Counter to list or set
ctrLists =Counter([1,2,3,4,2,3,1,4,5,1,7,3,6,8,2,9,8,4,7,1,9,2,8,3,7,3,7,4,5,6])
print(list(ctrLists))
print(set(ctrLists))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
set([1, 2, 3, 4, 5, 6, 7, 8, 9])
  • defaultdict
    • dictionary like object
    • never gives a ‘KeyError’ if a key is not found
# Example without a defaultdict
myDict = []
print(myDict['first']) 
TypeErrorTraceback (most recent call last)
<ipython-input-16-2bc8b8b35da3> in <module>()
 1 # Example without a defaultdict
 2 myDict = []
----> 3 print(myDict['first']) TypeError: list indices must be integers, not str
# Example with a defaultdict
from collections import defaultdict
myDict = defaultdict(object)
myDict['first']
for dictItem in myDict: print(dictItem) 
first
myDict = defaultdict(lambda: 0)
myDict['first']
0
  • OrderedDict
    • a dictionary subclass that remembers the order in which its data is added.
from collections import OrderedDict
myDict = OrderedDict() myDict['one'] = '1'
myDict['two'] = '2'
myDict['three'] = '3'
myDict['four'] = '4'
myDict['five'] = '5' for ky, vl in myDict.items(): print(ky, vl)
one 1
two 2
three 3
four 4
five 5 
  • namedtuple
    • instead of an index based references it can use index as well as name.
from collections import namedtuple
Student = namedtuple('Student','name age gender') naeem = Student(name='Naeem', age=39, gender="Male" )
print(naeem)
print(naeem.name)
print(naeem.gender)
maria = Student(name='Maria', age=37, gender="Female" )
print(maria)
print(maria.name)
print(maria.gender) 
Student(name='Naeem', age=39, gender='Male')
Naeem
Male
Student(name='Maria', age=37, gender='Female')
Maria
Female

 

datetime module

  • supports date function
  • supports time function
  • time function
In [1]:
# Import the datetime module
import datetime
tm = datetime.time(10,29,55)
print tm
10:29:55
print('Hour :', tm.hour)
print('Minute:', tm.minute)
print('Second:', tm.second)
print('MicroSecond:', tm.microsecond)
print('tzinfo:', tm.tzinfo) print('Min Value:', datetime.time.min)
print('Max Value:', datetime.time.max)
print('Resolution:', datetime.time.resolution) 
('Hour :', 10)
('Minute:', 29)
('Second:', 55)
('MicroSecond:', 0)
('tzinfo:', None)
('Min Value:', datetime.time(0, 0))
('Max Value:', datetime.time(23, 59, 59, 999999))
('Resolution:', datetime.timedelta(0, 0, 1))
  • date function
todaysDate = datetime.date.today()
print(todaysDate)
print('CTime:', todaysDate.ctime()) print('Year :', todaysDate.year)
print('Month:', todaysDate.month)
print('Day :', todaysDate.day) print('tuple:', todaysDate.timetuple())
print('ordinal:', todaysDate.toordinal()) print('Min Date:', datetime.date.min)
print('Max Date:', datetime.date.max)
print('Resolution:', datetime.date.resolution)
2018-03-28
('CTime:', 'Wed Mar 28 00:00:00 2018')
('Year :', 2018)
('Month:', 3)
('Day :', 28)
('tuple:', time.struct_time(tm_year=2018, tm_mon=3, tm_mday=28, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=87, tm_isdst=-1))
('ordinal:', 736781)
('Min Date:', datetime.date(1, 1, 1))
('Max Date:', datetime.date(9999, 12, 31))
('Resolution:', datetime.timedelta(1))
print('Current Local Time', datetime.datetime.now())
print('Current UTC Time', datetime.datetime.utcnow())
('Current Local Time', datetime.datetime(2018, 3, 28, 22, 54, 42, 908000))
('Current UTC Time', datetime.datetime(2018, 3, 29, 3, 54, 42, 908000))
dt1 = datetime.datetime.now()
dt2 = datetime.datetime.utcnow()
dt= dt2-dt1
print(dt)
print('Delta(days) :', dt.days)
print('Delta(seconds) :', dt.seconds)
5:00:00
('Delta(days) :', 0)
('Delta(seconds) :', 18000)

 

Python Debugging

  • Python supprts a module – pdb and a method set_trace() to debug a code
import pdb
a=10
b="naeem"
pdb.set_trace()
c= a+b
print(c)
--Return--
> <ipython-input-26-3c4522c8a755>(5)<module>()->None
-> pdb.set_trace()
(Pdb) a
(Pdb) print a
10
(Pdb) print b
naeem
(Pdb) a +b
(Pdb) print(a+b)
*** TypeError: unsupported operand type(s) for +: 'int' and 'str'
(Pdb) q
BdbQuitTraceback (most recent call last)
<ipython-input-26-3c4522c8a755> in <module>()
 3 a=10
 4 b="naeem"
----> 5 pdb.set_trace()
 6 c= a+b
 7 print(c) C:\ProgramData\Anaconda2\lib\bdb.pyc in trace_dispatch(self, frame, event, arg)
 51 return self.dispatch_call(frame, arg)
 52 if event == 'return':
---> 53 return self.dispatch_return(frame, arg)
 54 if event == 'exception':
 55 return self.dispatch_exception(frame, arg) C:\ProgramData\Anaconda2\lib\bdb.pyc in dispatch_return(self, frame, arg)
 89 finally:
 90 self.frame_returning = None
---> 91 if self.quitting: raise BdbQuit
 92 return self.trace_dispatch
 93 BdbQuit:

 

timeit module

import timeit
# lets compare the time to execute 3 types of ways of generating a line
# For loop - see lopps is slowest
timeit.timeit('"-".join(str(n) for n in range(1000))', number=10000)
1.8423546607142391
# List comprehension
timeit.timeit('"-".join([str(n) for n in range(1000)])', number=10000)
1.6530725293351622
# Map() ---- see map is fastest
timeit.timeit('"-".join(map(str, range(1000)))', number=10000)
1.0226760611147299

 

Regular Expressions

  • are used to text matching or parsing
  • used effectively in lot of tasks like data clean up, parsing data, pattern matching
  • Python uses a module ‘re’ for regular expressions
  • How to search : match = re.match(searchword, searchsource) returns a boolean
  • How to find location of search : match.start() and match.end() return the start and end locations of the search
  • How to find all instances of a search word : all = re.findall(searchword, searchsource)
from __future__ import print_function
import re
searchwords =['Redis', 'port', 'server']
logdata = 'Redis version=4.0.9, bits=64, pid=1, just started, Redis Running mode=standalone, port=6379.'
for searchword in searchwords: print('Searching word: "%s" in log: "%s".' %(searchword, logdata)) match = re.search(searchword, logdata) if(match): print('Successfully searched word: "%s", match start: %d, match end: %d' %(searchword, match.start(), match.end())) else: print('Could not search word: "%s"' %(searchword))
Searching word: "Redis" in log: "Redis version=4.0.9, bits=64, pid=1, just started, Redis Running mode=standalone, port=6379.".
Successfully searched word: "Redis", match start: 0, match end: 5
Searching word: "port" in log: "Redis version=4.0.9, bits=64, pid=1, just started, Redis Running mode=standalone, port=6379.".
Successfully searched word: "port", match start: 82, match end: 86
Searching word: "server" in log: "Redis version=4.0.9, bits=64, pid=1, just started, Redis Running mode=standalone, port=6379.".
Could not search word: "server"
searchword ='Redis'
logdata = 'Redis version=4.0.9, bits=64, pid=1, just started, Redis Running mode=standalone, port=6379.'
match = re.findall(searchword, logdata)
print(match)
if(match): print('Successfully searched word: "%s"' %(searchword))
else: print('Could not search word: "%s"' %(searchword))
['Redis', 'Redis']
Successfully searched word: "Redis"
#using a function for search
def myfindall(searchwords,searchsource): '''
 This function searches the searcwords in search source
 and returns all the matches
 ''' for searchword in searchwords: print('Searching searchword: %r' %(searchword)) print(re.findall(searchword,searchsource)) print('\n')
myfindall(searchwords, logdata)
Searching searchword: 'Redis'
['Redis', 'Redis'] Searching searchword: 'port'
['port'] Searching searchword: 'server'
[] 
  • Using Meta Characters
  • meta-character * means pattern must appear zero or more times.
  • meta-character + means pattern must appear at least once.
  • meta-character ? means pattern must appears zero or one time.
  • meta-character {x} means pattern must appears x number of times
  • meta-character {x, y } means pattern must appears x to y number of times in a range
searchsource = 'Za?..pqrs..pppqqq...stttsttt...efef!...Xpxxxx baaaa 123'
searchpatterns = [ 'sd*', # s followed by zero or more d's 'sd+', # s followed by one or more d's 'sd?', # s followed by zero or one d's 'sd{3}', # s followed by three d's 'sd{2,3}', # s followed by two to three d's 's[sd]+', # s followed by one or more s or d '[sd]', # either s or d '[^!.? ]' # check for matches that are not a !,.,?, or space '[a-z]+', # sequences of lower case letters '[A-Z]+', # sequences of upper case letters '[a-zA-Z]+', # sequences of lower or upper case letters '[A-Z][a-z]+' # one upper case letter followed by lower case letters r'\d+', # sequence of digits r'\D+', # sequence of non-digits r'\s+', # sequence of whitespace r'\S+', # sequence of non-whitespace r'\w+', # alphanumeric characters r'\W+', # non-alphanumeric ] myfindall(searchpatterns, searchsource) 
Searching searchword: 'sd*'
['s', 's', 's'] Searching searchword: 'sd+'
[] Searching searchword: 'sd?'
['s', 's', 's'] Searching searchword: 'sd{3}'
[] Searching searchword: 'sd{2,3}'
[] Searching searchword: 's[sd]+'
[] Searching searchword: '[sd]'
['s', 's', 's'] Searching searchword: '[^!.? ][a-z]+'
['Za', 'pqrs', 'pppqqq', 'stttsttt', 'efef', 'Xpxxxx', 'baaaa'] Searching searchword: '[A-Z]+'
['Z', 'X'] Searching searchword: '[a-zA-Z]+'
['Za', 'pqrs', 'pppqqq', 'stttsttt', 'efef', 'Xpxxxx', 'baaaa'] Searching searchword: '[A-Z][a-z]+\\d+'
[] Searching searchword: '\\D+'
['Za?..pqrs..pppqqq...stttsttt...efef!...Xpxxxx baaaa '] Searching searchword: '\\s+'
[' ', ' '] Searching searchword: '\\S+'
['Za?..pqrs..pppqqq...stttsttt...efef!...Xpxxxx', 'baaaa', '123'] Searching searchword: '\\w+'
['Za', 'pqrs', 'pppqqq', 'stttsttt', 'efef', 'Xpxxxx', 'baaaa', '123'] Searching searchword: '\\W+'
['?..', '..', '...', '...', '!...', ' ', ' '] 
# splitting using regular expressions
print(re.split(',',"name,age,gender"))
print(re.split(',',"naeem,21,M"))
print(re.split('\t',"name\tage\tgender"))
print(re.split('\t',"naeem\t21\tM"))
print(re.split(',',"name,age,gender"))
print(re.split(',',"naeem,21,M"))
print(re.split('\|',"name|age|gender"))
print(re.split('\|',"naeem|21|M"))
['name', 'age', 'gender']
['naeem', '21', 'M']
['name', 'age', 'gender']
['naeem', '21', 'M']
['name', 'age', 'gender']
['naeem', '21', 'M']
['name', 'age', 'gender']
['naeem', '21', 'M']

 

Advanced Objects and Data structures

  • Pythons supports lots of advanced objects as well as data structures
  • Advanced Numbers
# Hexadecimals
print(hex(255))
print(hex(1000)) 
0xff
0x3e8
# Binary
print(bin(255))
print(bin(1024))
print(bin(512)) 
0b11111111
0b10000000000
0b1000000000
# Power
print(pow(5,3)) # means 5**3
print(5**3) # means 5**3
print(pow(2,8)) # means 2**8
print(2**8) # means 2**8
print(pow(2,8,4)) # means (2**8)%4
print((2**8)%4) # means (2**8)%4
print(pow(2,8,5)) # means (2**8)%5
print((2**8)%5) # means (2**8)%5
125
125
256
256
0
0
1
1
# Absolute
print(abs(-1234))
print(abs(+1234))
1234
1234
# Rounding 
myPI = float(22)/7
print(myPI)
print(round(myPI,2))
print(round(myPI,5))
3.14285714286
3.14
3.14286
  • Advanced Strings
# capitalize, upper, lower functions
myName = "mohd naeem"
print(myName.capitalize()) # capitalizes only 1st character
print(myName.title()) # capitalizes 1st character of each word
print(myName.upper()) # capitalizes only 1st character
print(myName.lower()) # capitalizes only 1st character
Mohd naeem
Mohd Naeem
MOHD NAEEM
mohd naeem
# count, find, center functions
myName = "mohd naeem"
print(myName.count('e')) # counts number of occurances of a character
print(myName.find('o')) # finds the position or location of 1st instance of a character
print(myName.upper().center(50,'#')) # counts number of occurrences of a character
2
1
####################MOHD NAEEM####################
# Is checker functions
print("naeem123".isalnum()) # checks alphanumeric
print("naeem".isalnum()) # checks alphanumeric
print("naeem".isalpha()) # checks alphabetic
print("naeem".islower()) # checks is lower
print("Naeem".islower()) # checks is lower
print("Mohd Naeem".istitle()) # checks is title
print("mohd naeem".istitle()) # checks is title
print(" ".isspace()) # checks is space
print("M".isspace()) # checks is space
print("Mohd Naeem".endswith('m')) # checks endswith
print("Mohd Naeem".startswith('M')) # checks endswith
print("Mohd Naeem".endswith('t')) # checks endswith
print("Mohd Naeem".startswith('l')) # checks endswith
print("Mohd Naeem".split(' ')) # splits the word on split character and returns the tuple
print("Mohd Naeem".split('N')) # splits the word on split character and returns the tuple
print("Mohd Naeem".partition('N')) # partitions the word on partition character and returns the tuple
print("Mohd Naeem".partition('d')) # partitions the word on partition character and returns the tuple
True
True
True
True
False
True
False
True
False
True
True
False
False
['Mohd', 'Naeem']
['Mohd ', 'aeem']
('Mohd ', 'N', 'aeem')
('Moh', 'd', ' Naeem')
  • Sets
myset =set() # defines a blank set
myset.add(1) # add an element to a set
myset.add(2)
myset.add(1)
myset.add(3)
myset.add(4)
newset=myset.copy() # copies a set ointo another
newset.add(5)
print(myset)
print(newset)
print(newset.difference(myset)) # checks the difference between 2 sets
print(newset.intersection(myset)) # checks the intersection between 2 sets
print(newset.union(myset)) # does a union
print(myset.issubset(newset)) # checks the 1 set is a subset of the other
print(myset.isdisjoint(newset)) # checks if 2 sets don't have anything common
print(newset.issuperset(myset)) # checks the 1 set is a superset of the other 
newset.discard(5) # discards an element in a set
myset.clear() # cleans up a set
newset.clear()
print(myset)
print(newset)
set([1, 2, 3, 4])
set([1, 2, 3, 4, 5])
set([5])
set([1, 2, 3, 4])
set([1, 2, 3, 4, 5])
True
False
True
set([])
set([])
  • Dictionaries
# dictionary comprehensions -not so common but is possible
{a:a**2 for a in range(10)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
mydict ={0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
for key in mydict.keys(): print(key)
for value in mydict.values(): print(value)
for item in mydict.items(): print(item)
0
1
2
3
4
5
6
7
8
9
0
1
4
9
16
25
36
49
64
81
(0, 0)
(1, 1)
(2, 4)
(3, 9)
(4, 16)
(5, 25)
(6, 36)
(7, 49)
(8, 64)
(9, 81)
  • Lists
mylist = [1,2,3,3,5]
mylist.append(4) # appends an element/elements to list as an element or as a set within the set
print(mylist)
mylist.extend([9]) # extends a set as an element
print(mylist)
mylist.append([6,7]) # appends an element to a list as an element or a set to an list as set
print(mylist)
mylist.extend([8,10]) # extends an element to list
print(mylist)
print(mylist.count(3)) # find the number of occurances of an items
print(mylist.index(9)) # find index of an element
mylist.pop() # pops 1st element
mylist.pop(7) # pops nth index 
print(mylist)
mylist.insert(0,99) # inserts at element at nth index
print(mylist)
mylist.remove(99) # removes an element
print(mylist)
mylist.reverse() # reverses a list
print(mylist)
mylist.sort() # sorts a list
print(mylist)
[1, 2, 3, 3, 5, 4]
[1, 2, 3, 3, 5, 4, 9]
[1, 2, 3, 3, 5, 4, 9, [6, 7]]
[1, 2, 3, 3, 5, 4, 9, [6, 7], 8, 10]
2
6
[1, 2, 3, 3, 5, 4, 9, 8]
[99, 1, 2, 3, 3, 5, 4, 9, 8]
[1, 2, 3, 3, 5, 4, 9, 8]
[8, 9, 4, 5, 3, 3, 2, 1]
[1, 2, 3, 3, 4, 5, 8, 9]

 

Multi-threading and Multiprocessing

  • In the normal Python programs we tried till date we used only 1 process and 1 thread(by default)
  • but its not efeective use of the resouces like CPU, Network bandwidth when it comes to I/O and CPU intesive applications.
  • I/O Intensive applications – they would consume more and more I/O bandwidth available
    • Reading and Writing files
    • Downloading content(image, media etc)
    • Sharing files over the network
    • Webscraping
  • CPU Intensive applications – they would consume more and more CPU available
    • Parallel processing e.g Big data
    • Data formatting, scrubbing, cleanups
    • computing
    • Image processing
  • Python is a very advanced language supporting lot of features to support Mutlithreading and Multiprocessing.4
  • Process Vs Thread
    • Process – it’s the running instance of a program. When we run any python program, its the process.
       - You can see the process using ps -a - This process also has atleast 1 thread - called Main(__main__) thread - You can configure and design to run a program which spwans into multiple processes
    • Thread – It is the path of execution of a program.
       - E.g. the Main Thread defines the path of execution of a program - You can configure and design to run a process which can spawn multiple threads. 
  • We will be using the Monte Carlo algorithm of evaluating PI using
    • single process with single thread
    • single process with multiple threads
    • multiple processes with mutiple threads
  • Example one – Single process with single thread
    • we will see that we get a value of PI but not very accurate
import random as myr
import math as mym
def getmyPI(num): # count of all darts which land inside. inside = 0 # total count of darts to throw. total = num # Iteratition for each dart thrown for i in range(0, total): # Generate random x, y  x2 = myr.random()**2 y2 = myr.random()**2 # Increment inside, if inside the circle. if mym.sqrt(x2 + y2) < 1.0: inside += 1 # pi = (inside / total) * 4 mypi = (float(inside) / total) * 4 return mypi
# Value of mypi
print(getmyPI(10)) 
3.6
  • Example one – Single process with multiple thread
    • we will see that we get a better value of PI
%%writefile calcPI.py
from __future__ import print_function
import random as myr
import math as mym
from multiprocessing import Pool
import timeit def getmyPI(num): # count of all darts which land inside. inside = 0 # total count of darts to throw. total = num # Iteratition for each dart thrown for i in range(0, total): # Generate random x, y x2 = myr.random()**2 y2 = myr.random()**2 # Increment inside, if inside the circle. if mym.sqrt(x2 + y2) < 1.0: inside += 1 # pi = (inside / total) * 4 mypi = (float(inside) / total) * 4 return mypi # Value of mypi
if __name__ == '__main__': N = 10**5 # total iterations P = 1 # number of processes p = Pool(P) print(timeit.timeit(lambda: print(f'{sum(p.map(getmyPI, [N//P]*P))/P:0.5f}'), number=10)) p.close() p.join() print(f'{N} total iterations with {P} processes') 
Overwriting calcPI.py
! python calcPI.py
3.14264
3.13964
3.14692
3.14052
3.14360
3.14988
3.14716
3.14940
3.14348
3.14436
0.7282300670049153
100000 total iterations with 1 processes
  • Example one – Multiple process with multiple thread
    • we will see that we get an even better value of PI
%%writefile calcPI.py
from __future__ import print_function
import random as myr
import math as mym
from multiprocessing import Pool
import timeit def getmyPI(num): # count of all darts which land inside. inside = 0 # total count of darts to throw. total = num # Iteratition for each dart thrown for i in range(0, total): # Generate random x, y x2 = myr.random()**2 y2 = myr.random()**2 # Increment inside, if inside the circle. if mym.sqrt(x2 + y2) < 1.0: inside += 1 # pi = (inside / total) * 4 mypi = (float(inside) / total) * 4 return mypi # Value of mypi
if __name__ == '__main__': N = 10**5 # total iterations P = 5 # number of processes p = Pool(P) print(timeit.timeit(lambda: print(f'{sum(p.map(getmyPI, [N//P]*P))/P:0.5f}'), number=10)) p.close() p.join() print(f'{N} total iterations with {P} processes') 
Overwriting calcPI.py
! python calcPI.py
3.14112
3.14020
3.13136
3.14160
3.14680
3.13476
3.14848
3.13976
3.13380
3.14568
0.38084139800048433
100000 total iterations with 5 processes

  This is the end of this article.