You are on page 1of 4

1 # Module 5 exercise

2 import re
3 ######################### Regex ####################################
4 # Given the following data:
5 str1 = "The answer is 42"
6 str2 = "What... is the air speed of an unladen swallow?"
7 str3 = "3.15; 2.383 and 11.039*2.77 1257.11"
8 str4 = "2020 / 08 / 14"
9 inList = [str1, str2, str3, str4]
10 # 1. Write regex to print the string if the string has:
11 # a. a digit
12 for s in inList:
13 if re.search("\d", s): #searches for 1 digit
14 print(s)
15 print()
16 # b. a number that's at least 3 digit long
17 for s in inList:
18 if re.search("\d{3}", s):
19 print(s)
20 print()
21 # c. no letters
22 for s in inList:
23 if re.search("^[^a-zA-Z]+$", s): #[a-zA-Z] is 1 char in the set of all letters
24 print(s) #[^a-zA-Z] is 1 char in the set of non letters
25 #[^a-zA-Z]+ is multiple chars in set of non leters
26 print() #^[^a-zA-Z]+$ is for a line where all chars are in the set of non letters
27 # 2. Write a regex to print
28 # a. the 3 numbers of str4
29 str4 = "2020 / 08 / 14"
30 m = re.search("(\d+) / (\d+) / (\d+)",str4) #if you know there is space,slash,space then this easier to read
31 #m = re.search("(\d+)\W+(\d+)\W+(\d+)",str4) #if you want to be more flexible about what's between the numbers
32 #more flexible, user could write 2020-14-9, 2020 /14/ 9
33
34 print(m.group(1), m.group(2), m.group(3))
35 print() #prints 20200814
36 # b. the start location of the 3 numbers of str4
37 print(m.start(1), m.start(2), m.start(3))
38 print() #prints 0 7 12
39
40 # 3. Write a regex to print:
41 # a. the first word of str2
42 str2 = "What... is the air speed of an unladen swallow?"
43 m = re.search("(\w+)\W+(\w+)", str2)
44 print(m.group(1), m.group(2))
45 print()
46
47 # b. the last word of str2
48 m = re.search("(\w+).$", str2) #a word, one more character, then end of string
49 print(m.group(1))
50 print()
51
52 # c. both the first and last words of str2
53 m = re.search("(\w+).* (\w+).$", str2) # * and + are both greedy matching,
54 # the * comes first(on left) therefore it has
55 # higher precedence so it can grab as many chars as it wants,
56 # only backing up to allow 1 \w at the end
57 # (word, up to the last space, last word)
58 print(m.group(1), m.group(2))
59 print()
60
61 str2 = "What... is the air speed of an unladen swallow?"
62 # d. str2 with spaces changed to underscore
63 print (re.sub(" ", "_", str2))
64 print()
65
66 # e. str2 with the ellipsis (...) removed
67 # 3 ways
68 print (re.sub("\.\.\.", "", str2))
69 print (re.sub("\.{3}", "", str2))
70 print (re.sub("[.]{3}", "", str2))
71 print()
72
73
74 # 4. Use regex to print only floating point numbers with 2 digit
75 # after the decimal point in str3
76 str3 = "3.15; 2.383 and 11.039*2.77 1257.11"
77 #use findall: returns list of all substrings that match
78 print(re.findall("\d+\.\d{2}\\b",str3)) #\\b - don't want any character that is not a word
79 print() #\d = 1 digit \. = 1 period \d{2} = 2 digits
80
81 # 5. Write a loop that asks the user input for a birth date.
82 # Keep asking until you get a valid birth date.
83
84 # Validate the user input with the following steps:
85 # a. check that the format of str4 is valid: yyyy-mm-dd
86
87 # b. check that the month is 1-12, day is valid for the
88 # month (28, 30, or 31), and the year is between 1900 and 2100
89
90 # c. then print the date as mm/dd/yyyy
91
92 #a
93
94 days = dict(zip(tuple(range(1,13)), (31,28,31,30,31,30,31,31,30,31,30,31))) #dictionary 1-12 with days for each month
95 #tuples are immutable, and faster than lists
96
97 done = False
98 while not done:
99 bday = input("Enter birthday yyyy-mm-dd: ")
100 #m = re.search("\d{4}-\d{2}-\d{2}") #minimum check
101 m = re.search("\s*(\d{4})\s*-\s*(\d{2})\s*-\s*(\d{2})\s*", bday) #allow for optional spaces (\s* allows optional spaces)
102 #( ) between each \d{4} or \d{2}
103
104 if not m: #m is None, there is no match object
105 print("Format must be yyyy-mm-dd")
106 continue #stop current iteration of loop and go back to top of loop (Good for error checking)
107 #if there is a match, skips to here
108 yy = m.group(1) #year
109 mm = m.group(2) #month
110 dd = m.group(3) #day
111 if not 1900 < int(yy) < 2100:
112 print("Year must be 1900-2100")
113 continue #Jumps to while loop if not
114 if not 1 <= int(mm) <= 12:
115 print("Month must be 1-12")
116 continue
117 if not 1 <= int(dd) <= days[int(mm)]:
118 print("Days must be 1-" + str(days[int(mm)]))
119 continue
120 #by the time we get here, everything is good
121 print(mm + "/" + dd + "/" + yy)
122 done = True
123
124
125 ############# Functions as first class objects ##################
126
127
128 def greeting(text1, text2="", text3="How are you?") :
129 print(text1, text2)
130 print(text3)
131
132 greeting("hello") # what will be printed?
133 # hello
134 # How are you?
135
136 # 6. explain why each of the following lines will work or not work
137 fctA = greeting("hola") # will print hola and How are you. [greeting("hola") calls the greeting function correctly].
138 # ^ this is a function call
139 #fctA("ciao") # not work: since fctA is None, we can't "run" it
140
141 fctB = greeting #fctB is another reference to the greeting function
142 fctB("ciao")
143
144
145
146 # 7. Write a function called doWork that accepts a function
147 # and a text string. doWork calls the function and passes the
148 # text string to the string
149
150 def doWork(f, text): #f accepts function, text accepts string
151 f(text) # runs greeting("aloha")
152
153 # call doWork and pass the function greeting and the string "aloha"
154
155 doWork(greeting, "aloha") #f is a reference to greeting, "aloha" is passed to text
156 #passes greeting(reference to function)
157 #passes "aloha"
158 #=========
159 # write a function doAnyWork that accepts a function and a
160 # variable argument list. doAnyWork calls the function and
161 # passes the argument list. doWnyWork returns the
162 # function's return value
163
164 # * here is packing
165 def doAnyWork(f, *args, **kwargs) : # a variable argument list is *args (to catch all positional args)
166 # and **kwargs (to catch all keyword args)
167 #f(args, kwargs) # pass 2 items: args(tuple) and kwargs(dictionary)
168 retval = f(*args, **kwargs) # pass a sequence of input args: positional first, keyword second
169 # * here is unpacking
170 return retval
171
172
173 doAnyWork(greeting, "hello", "CIS 41A") # greeting("hello", "CIS 41A")
174 # ^text1 ^text2
175
176 # will print hello CIS41A
177 # How are you?
178
179
180
181
182 # will this work?
183 L = "hello there CIS41A".split() # L is list of 3 elements, ['hello', 'there', 'CIS41A']
184
185
186 doAnyWork(greeting, L) # if this works, what does it print?
187 # Yes, will print list
188 # ['hello', 'there', 'CIS41A']
189 # How are you?
190
191
192 doAnyWork(greeting, *L) # if this works, what does it print?
193 # hello there
194 # CIS41A
195
196 # *L unpacks list to 3 separatevalues. (text1 = hello, text2 = there, text3 = CIS41A)
197
198
199 # will any of the following print statements run successfully?
200 def add2(n1, n2=0) :
201 return n1 + n2
202
203
204 #def doAnyWork(f, *args, **kwargs) :
205
206 print(doAnyWork(add2, 5)) # f: add2, args = (5,), kwargs = { } -> output = 5+0 = 5
207 # equivalent to add(5)
208
209 print(doAnyWork(add2, 6, 7)) # f: add2, args = (6, 7), kwargs = { } -> output = 6+7 = 13
210 # equivalent to add(6,7)
211
212 print(doAnyWork(add2, n2=8, n1=3)) # f: add2. args = ( ), kwargs = {"n2":8, "n1":3}
213 # add2(n2=8, n1=3)
214 # output = 11
215
216 #print(doAnyWork(add2, 1, 2, 3)) # f: add2. args = (1,2,3), kwargs = {}
217 # add2(1,2,3)
218 # output = error, only expects 2
219
220
221 '''
222 Does this mean i should write all my functions as def fA(*args, **kwargs):
223 No.
224 Most of the time we want to specify the paramter list such as
225 def fA(name, gpa=0.0, studentID= 0):
226
227 because:
228 1. The caller knows what we expect, and can pass the correct argumets
229 2. for the function fA itself, it's much easier to refer to "name" or "gpa" than arg[0] and arg[1]
230
231
232 When to use *args/ **kwargs? :
233 Answer:
234 1.When the function itself does not need to access args and kwargs
235 and simply need to pass them along to another function
236 2. If the function itself needs to be flexible with number of arguments
237 (Can accept any numebr of arguments)
238
239 '''
240
241 ########################### Generator ##########################
242 # 8. If you need to write a generator that produces fibonacci
243 # numbers, where the current value is the sum of the 2 previous
244 # values, would you use a generator function or generator expression?
245 # Why?
246
247 # Write the fibonacciGen generator
248 #Write a generator function since this is infinite sequence
249
250 def fibonacciGen() :
251 prev, num = 0, 1
252 while True:
253 yield num
254 num, prev = num + prev, num
255
256 fgen = fibonacciGen() # what is fgen? #-> fgen is a reference to a generator
257 for i in range(6):
258 print(next(fgen)) #get the next value
259
260
261 # to here, prints 1st 2nd 3rd4th 5th 6th value
262 print(next(fgen)) # print 7th value
263

PDF document made with CodePrint using Prism

You might also like