14. Exercise 7 – a fix
14
• assign “1” to the arg of split() - maxsplit
data = open("dialogue_chinese.txt", encoding="utf-8")
for line in data:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
17. Decisions to make
17
If not line.find(“:”) == -1
#dosomething
Print()
• Put extra control logic to check and correct split error
• Endless check if data format changes again
• too many flows cause code unreadable
19. Try/Except
try:
#do your operations here;
except ExceptionI:
#If there is ExceptionI, then execute this block.
except ExceptionII:
#If there is ExceptionII, then execute this block.
else:
#If there is no exception then execute this block.
finally:
#This would always be executed.
20. Exercise 8 - A fix by Try/Except
data = open("dialogue_chinese.txt", encoding="utf-8")
for line in data:
try:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
except:
pass
data.close()
Do nothing
21. Exercise 8 – another problem
def print_file():
filename = input("輸入要開啟的檔名:")
data = open(filename, encoding="utf-8")
for line in data:
try:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
except:
pass
data.close()
print_file()
輸入要開啟的檔名: diagoue.txt
What if file doesn’t exist – you put incorrect filename
22. Exercise 8 – one way to fix
import os
def print_file():
filename = input("輸入要開啟的檔名:")
if os.path.exists(filename):
data = open(filename, encoding="utf-8")
for line in data:
try:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
except:
pass
data.close()
else:
print("檔名不存在")
>>> print_file()
>>> 輸入要開啟的檔名: diagoue.txt
檔名不存在
• Extra check-logic version
23. Exercise 8 – one way to fix
def print_file():
filename = input("輸入要開啟的檔名:")
try:
data = open(filename, encoding="utf-8")
for line in data:
try:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
except:
pass
data.close()
except:
print("檔名不存在")
>>> print_file()
>>> 輸入要開啟的檔名: diagoue.txt
檔名不存在
• Try-except version
Less is better!!
Complexity creates more problem and
prevent you from making right thing
24. Exercise 8 – one way to fix
try:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
except:
pass
• Be specific for the exception you gonna catch
This bypass all runtime error. you
may not notice other bugs and don’t
know how to handle afterward
filename = input("輸入要開啟的檔名:")
try:
data = open(filename, encoding="utf-8")
for line in data:
try:
(role,line_spoken) = line.split(":",maxsplit=1)
print(role,end="")
print("說: ", end="")
print(line_spoken, end="")
except ValueError:
pass
data.close()
except IOError as err:
print(err)
26. Full handling clause
• Try / Finally / else clauses
try:
fh = open("testfile", "w")
fh.write("This is my test file for exception handling!!")
finally:
print("Error: can't find file or read data")
try:
fh = open("testfile.txt", "w")
fh.write("This is my test file for exception handling!!")
except IOError as e:
print("Error: can't find file or write data")
print(e)
else:
print ("Written content in the file successfully")
29. Raising an Exception
• User defined exception - MyAppLookUpError
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
def password_check(passwd):
if len(passwd) < 1:
raise MyAppLookupError("MyAppPasswordFormatError: length is
{}".format(len(passwd)))
if passwd.find('*') != -1:
raise MyAppLookupError("MyAppPasswordFormatError: contains *")
password = ""
try:
password_check(password)
except Exception as e:
print(e)
Inherit from baseclass : BaseException
34. • The function only executes on next() or forloop
• A generator is a one-time operation,
Generator function
>>> a = countdown(3)
>>> next(a)
Counting down from 3
3
>>> next(a)
2
>>> next(a)
2
>>> next(a)
1
>>> next(a)
One-time, exception
once it’s consumed
36. def firstn_list(n):
num, nums = 0, []
while num <= n:
nums.append(num)
num += 1
return nums
>>> sequnce_nums = firstn_list(10000)#10**5
>>> sum(sequnce_nums)
49995000
By normal function
• Let’s create a list and sum each up
• [0,1,2,3,4,………………,10000]
Here nums contains 10000
num variable in the memory
0
0 1 2
1
..
2 …
9999
10000
nums[]
Run
37. def firstn_generator(n):
num = 0
while num < n:
yield num
num += 1
>>>sequnce_nums = firstn_generator(10000)#10**5
>>>sum(sequnce_nums)
49995000
By generators function
1 2 … 10000
Run
1st
Run
2nd
Run
..th
Run
10000
num num num num
49. list-processing features
S = ['IBM',50,91.10]
s.append(x) # Append x to end of s
s.extend(t) # Add items in t to end of s
s.count(x) # Count occurences of x in s
s.index(x) # Return index of x in s
s.insert(i,x) # Insert x at index i
s.remove(x) # Remove first occurence of x
s.reverse() # Reverses items in list
s.sort() # Sort items in s in-place
• Python has a lot of list-processing features
50. list-processing features
x = [1, 2, -3, 4, -5]
a = []
for i in x:
if i > 0:
a.append(2*i)
• If we want to create a new list in which each element is
doubled in the old list when old value is not negative
• One way use forloop iterate
5 lines of code
51. List Comprehensions
• General syntax
[expression for x in s if condition]
• What it means
result = []
for x in s:
if condition:
result.append(expression)
• Can be used anywhere a sequence is expected
>>> a = [1,2,3,4]
>>> sum([x*x for x in a])
30
52. List Comprehensions
>>> x = [1, 2, -3, 4, -5]
>>> a = [i*2 for i in x if i > 0]
>>> b
[2,8,4,20]
• Same case by list comprehension
2 lines of code
53. List Comprehensions
• ASCII and str interchange between map
>>> ord('s')
115
>>> res = []
>>> for x in 'spam':
res.append(ord(x))
>>> res
[115, 112, 97, 109]
Content: http://www.ascii-code.com/
>>> res = list(map(ord, 'spam'))
>>> res
[115, 112, 97, 109]
>>> res = [ord(x) for x in 'spam']
>>> res
[115, 112, 97, 109]
Stand list
processing
Use map() to
combine ord()
Use map() to
combine ord()
54. List Comprehensions
• nested loop: we want to add each element from a ,b
a, b = [0, 1, 2] , [100,200,300]
>>> res = []
>>> for x in a:
for y in b:
res.append(x+y)
>>> res
[100, 200, 300, 101, 201, 301, 102, 202, 302]
>>>[x+y for x in a for y in b]
>>> res
[100, 200, 300, 101, 201, 301, 102, 202, 302]
Use 2 forloops
Finish on 1 line
56. Exercise 10 – transfer for to list comp (2)
>>>result = []
>>>for x in range(5):
if x % 2 == 0
for y in range(5):
if y % 2 == 1:
result.append((x,y))
• Intervene ‘even number’ with ‘odd number’ in one to five to
[(0,1),(0,3),(2,1)…..]
even
odd
57. Exercise 10– Answer(1)
>>> [x + y for x in 'spam' for y in 'SPAM']
['sS', 'sP', 'sA', 'sM', 'pS', 'pP', 'pA', 'pM',
'aS', 'aP', 'aA', 'aM', 'mS', 'mP', 'mA', 'mM']
Intervene ‘spam’ with ‘SPAM’ to
58. Exercise 10– Answer(2)
>>> [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
Intervene even and odd number
65. Generator Expressions
>>> G = (x ** 2 for x in range(4))
>>> iter(G) is G # iter(G) optional: __iter__ returns self
True
>>> next(G) # Generator objects: automatic methods
0
>>> next(G)
1
>>> next(G)
4
>>> next(G)
9
>>> next(G)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> G
<generator object <genexpr> at 0x00000000029A8318>
66. Exercise 11 – make Generator
wwwlog = open("access-log")
total = 0
for line in wwwlog:
bytestr = line.rsplit(None,1)[1]
if bytestr != '-':
total += int(bytestr)
print "Total", total
81.107.39.38 - ... "GET /ply/ply.html HTTP/1.1" 200 97238
81.107.39.38 - ... "GET /ply/ HTTP/1.1" 304 -
• Find out how many bytes of data were transferred
76. Functional programming
expr, result = "28+32+++32++39", 0
for t in expr.split("+"):
if t != "":
res += int(t)
print result
Imperative style = actions that change state from initial state to result
85. Functional tools - filter
filter()
• filter out all the elements of a list, for which the function returns True
• filter(func, SEQ)
filter(lambda x: x % 2, [0,1,2,3])
[1,3]
filter(lambda x: x % 2 == 0, [0,1,2,3])
[2,4]
f returns a Boolean value, i.e. either True or False
Leave it in list If x%2 is True - get odd num
Even num
Code credited http://www.python-course.eu/lambda.php
86. Functional tools - reduce
reduce()
• continually applies the function func() to the sequence seq. It returns a
single value
• reduce(func, SEQ)
>>>reduce(lambda x,y: x+y, [47,11,42,13])
113
Func(Func(Func(47,11),42),13)
Code credited http://www.python-course.eu/lambda.php
88. More Python FP
• Functools
• Itertools
• Generators
• Decorators
More on PYTHON FP:
https://newcircle.com/bookshelf/python_fundamentals_tutorial/functional_programming
http://thecodeship.com/patterns/guide-to-python-function-decorators/
Function decorators are simply wrappers to existing functions.
98. OS - Operating System Interface
98
>>> import os
>>> os.getcwd() # Return the current working directory
'C:Python35'
>>> os.chdir('/server/accesslogs') # Change current
working directory
>>> os.system('mkdir today') # Run the command mkdir in
the system shell 0
More on
https://docs.python.org/3/library/os.html#module-os
99. Sys - System-specific parameters and
functions
99
$python demo.py one two three
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']
More on https://docs.python.org/3/library/os.html#module-os
argv[0]
Script name
argv[1:]
Arg1 - n
>>> import sys
>>> sys.version
‘3.6.5 (r265:79063, Apr 16 2016, 13:57:41) n[GCC 4.4.3]'
>>> sys.version_info
(3, 6, 5, 'final', 0)
Command Line Arguments
Information on the Python Interpreter
104. Regular expression (Regex)
104
• A regular expression is a special sequence of characters that
helps you match or find other strings or sets of strings, using a
specialized syntax held in a pattern.
• Regular expressions are widely used in UNIX world.
• Especially used for detecting word pattern
re.match(pattern, string, flags=0) #flag uses | (OR)
re.search(pattern, string, flags=0)
re.sub(pattern, repl, string, max=0)
match checks for a match only at the beginning of the string,
not quite useful compared with search
Search checks for a match anywhere in the
string
105. Regular expression (Regex)
105
>>> import re
>>> wordlist = ['hbasgoed', 'abhshooe', 'hbatisgoe', 'tbgoe', 'tbortgoe','abaisoed',
'abandoned', 'abased', 'abashed', 'abatised', 'abed', 'aborted','abaisogoe',
'abandongoe']
>>> [w for w in wordlist if re.search('ed$',w)]
['abaissed', 'abandoned', 'abased', 'abashed', 'abatised', 'abed', 'aborted']
• Detecting word pattern
Let's find words ending with ed using the regular expression
Let's find puzzle crossword for 8 letters with ‘a’ as its third letter and ‘y’ as sixth
>>> [w for w in wordlist if re.search('^..a..o..$',w)]
['hbasgoed', 'abaisoed']
. wildcard symbol match any single character
^ match beginning of line.
$ Matches end of line.
106. Regular expression (Regex)
106
>>> wordlist = ['abjectly', 'adjuster', 'gold','golder','dejected', 'golf', 'dejectly',
'injector', 'majestic','hold', 'hole']
>>> [w for w in wordlist if re.search('^[ghi][mno][jlk][def]$',w)]
['gold', 'golf', 'hold', 'hole']
>>> [w for w in wordlist if re.search('^[ghi][mno][jlk][def]',w)]
['gold', 'golder', 'golf', 'injector', 'hold', 'hole']
Ranges and Closures
Let’s find 4 letters word in which the first ranges from ‘g’,’h’ or ‘I’, the second ‘m’, ‘n’ or ‘o’
As 4653 in T9 system
the regular expression: ^[ghi][mno][jlk][def]$
Content credited http://www.nltk.org/images/T9.png
107. Regular expression (Regex)
107
>>> chat_words = ['miiinnee', 'mmmmmmmmiiiiiiiiinnnnnnnnneeeeeeee',
'mine','me','mingg','mi','ne' ]
>>> [w for w in chat_words if re.search('^m+i+n+e+$', w)]
['miiinnee', 'mmmmmmmmiiiiiiiiinnnnnnnnneeeeeeee', 'mine']
>>> [w for w in chat_words if re.search('^m*i*n*e*$', w)]
['miiinnee', 'mmmmmmmmiiiiiiiiinnnnnnnnneeeeeeee', 'mine', 'me', 'mi', 'ne']
Ranges and Closures
• + symbol means "one or more instances of the preceding item", which could be an
individual character like m, a set like [fed] or a range like [d-f]
• * symbol means "zero or more instances of the preceding item".
• The regular expression ^m*i*n*e*$ will match ^m+i+n+e+$
• e.g. me, min, and mmmmm.
108. Regular expression (Regex)
108
Ranges and Closures
: escape a control character
{n,m}: Matches n or more occurrences of preceding expression
(): Groups regular expressions
python|ruby: match “python” or “ruby”
digitlist = ['123','331-points', '0.0085', 'Adopting','C$','0.05','abv','2016'
'0.1', 'JAP#','92.2','911-ppppppp''43643', '1978', 'US$','1.1253553','bread-and-
butter','PO@','10-year','1.14', 'Advancing','1.1650', 'savings-and-loan','1.17',
'1.0','10-day','331-bigpoints', 'Absorbed']
>>> [w for w in digitlist if re.search('(ed|ing)$', w)]
['Adopting', 'Advancing', 'Absorbed']
>>> [w for w in digitlist if re.search('^[0-9]+.[0-9]+$', w)]
['0.0085', '0.05', '20160.1', '92.2', '1.1253553', '1.14', '1.1650', '1.17', '1.0']
>>> [w for w in digitlist if re.search('^[A-Z]+$$', w)]
['C$', 'US$']
>>> [w for w in digitlist if re.search('^[0-9]{4}$', w)]
['1978']
>>> [w for w in digitlist if re.search('^[0-9]+-[a-z]{3,5}$', w)]
['10-year', '10-day']
109. Regular expression (Regex)
109
>>> word1 = 'smartdog smatdog ldoedog ddwwlaj'
>>> re.findall('dog',word1)
['dog', 'dog', 'dog']
>>> word = 'supercalifragilisticexpialidocious'
>>> re.findall('[aeiou]', word)
['u', 'e', 'a', 'i', 'a', 'i', 'i', 'i', 'e', 'i', 'a', 'i', 'o', 'i', 'o',
'u']
Findall()
finds all (non-overlapping) matches of the given regular expression
126. Class
• Employee Class (a blueprint to employee data)
class Employee:
"""Common base class for all employees"""
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print("Name : ", self.name, ", Salary: ", self.salary)
Class Variable
Classname.var
Memebr variable
Different in each object
128. Class
• class-related BIFs
• dir(): show all supported methods and attributes
• help(): display class info
• Isinstance(x,y): check if x is the object of y
>>> dir(paul)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'displayCount', 'displayEmployee', 'empCount', 'name', 'salary']
>>> paul.__doc__
'Common base class for all employees'
>>> >>> help(paul)
Help on Employee in module __main__ object:
class Employee(builtins.object)
| Common base class for all employees
| Methods defined here:
| __init__(self, name, salary)
| Initialize self. See help(type(self)) for accurate signature.
| displayCount(self)
>>> >>> isinstance(paul,Employee)
True
130. __del__()
• Python interpreter invokes this func when the object is no longer
used – release memory
class Employee:
"""Common base class for all employees"""
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def __str__(self):
return str(self.name)
def __del__(self):
print("delcalled:"+ self.__str__())
>>> paul = Employee('Paul',10000)
>>> paul = "lol"
delcalled:Paul
133. Encapsulation
class Encapsulation(object):
def __init__(self, a, b, c):
self.public = a
self._protected = b
self.__private = c
>>> from encapsulation import Encapsulation
>>> x = Encapsulation(11,13,17)
>>> x.public
11
>>> x._protected
13
>>> x._protected = 23
>>> x._protected
23
>>> x.__private
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Encapsulation' object has no attribute '__private'
Can be accessed inside/outside
Supposed to be retracted from
outside but python still allow
you to access
This changes virtually nothing
Can’t be accessed outsie
135. Exercise 13 – create your first class
• Enhance Employee class to support more operations:
• To support the below attributes:
• Instance attributes: name, grades, salary, position
• class attribute: managerCount , teacherCount, otherCount,
empCount
• To support the operations below:
• methods
• display_failure_count(): return sum of the failure class (the failure score is the subject
‘s score smaller than 60)
• add_grade(grade): to put class’s score like 100, 80 , 50
• Class Methods
• display_position_count(position)
• display_employee_count()
136. Exercise 13 – create your first class
paul = Employee('Paul',15000,"teacher")
jack = Employee('Jack',20000,"manager")
joy = Employee('Joy',15000,"writter")
mike = Employee('mike',20000,"teacher")
#add grade
paul.add_grade(100)
paul.add_grade(80)
paul.add_grade(90)
print("%s average grade:%d" % (paul.get_name(), paul.display_avg_grade()))
#add failure grade
paul.add_grade(40)
paul.add_grade(30)
paul.add_grade(58)
print("%s failed clount:%d" % (paul.get_name(), paul.display_failure_count()))
#check statistic by accessing class attribute by class methods
Employee.display_employee_count()
Employee.display_position_count("manager")
Employee.display_position_count("teacher")
Employee.display_position_count("other")
To test your employee class
139. Inheritance
• Implicit Inheritance:
• child will inherit all of its behavior from Parent.
class Parent(object):
def implicit(self):
print "PARENT implicit()"
class Child(Parent):
pass
>>> dad = Parent()
>>> son = Child()
>>> dad.implicit()
>>> son.implicit()
PARENT implicit()
PARENT implicit()
all subclasses (i.e., Child) will
automatically get those features
from base class (i.e., Parent)
141. Inheritance
• Alter
• overriding where you want to alter the behavior before or after the Parent class's
version runs.
class Parent(object):
def altered(self):
print "PARENT altered()"
class Child(Parent):
def altered(self):
print "CHILD, BEFORE PARENT altered()"
super(Child, self).altered()
print "CHILD, AFTER PARENT altered()"
>>> dad = Parent()
>>> son = Child()
>>> dad.altered()
>>> son.altered()
PARENT altered()
CHILD, BEFORE PARENT altered()
PARENT altered()
CHILD, AFTER PARENT altered()
use a Python built-in function
named super to get the Parent
version to call.
146. Polymorphism
a = "alfa"
b = (1, 2, 3, 4)
c = ['o', 'm', 'e', 'g', 'a']
>>>print(a[2])
>>>Print(b[1])
>>>Print(c[3])
f
2
g
Python uses polymorphism
extensively in built-in types. Here
we use the same indexing operator
for three different data types.
147. Polymorphism
class Bear(object):
def sound(self):
print "Groarrr"
class Dog(object):
def sound(self):
print "Woof woof!"
def makeSound(animalType):
animalType.sound()
bearObj = Bear()
dogObj = Dog()
makeSound(bearObj)
makeSound(dogObj)
Content credited: https://pythonspot.com/en/poylmorphism/
Polymorphism in Python with a function:
148. Polymorphism
class Animal:
def __init__(self, name=''):
self.name = name
def talk(self):# Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
print("Meow!")
class Dog(Animal):
def talk(self):
print("Woof!")
c = Cat("Missy")
c.talk()
d = Dog("Rocky")
d.talk()
Content credited: http://zetcode.com/lang/python/oop/
Polymorphism with abstract class
152. Generators Function
• The function only executes on next()
x = firstn_generator(10)
>>> x
<generator object at 0x58490>
>>>next(x)
0
>>>next(x)
1
Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration