1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# SI 413 Fall 2012
# Lab 11
# Python introduction
 
'''
This Python program will serve as a basic introduction to the language.
It has some basic changes for you to make too.
 
Note that this is a Python 3 program. You have to run it using the
"python3" command.
 
First things first, you notice that single-line comments in Python start
with a # symbol, like above. What we're in here is actually a multi-line
string, which is started and ended with 3 single or double quotes. But
multi-line strings like this one that aren't actually used anywhere can
also serve as comments. Like this!
'''
 
##### DEFINITIONS #####
 
'''
Variable declarations and redeclarations look exactly the same!
And there are no declared types, of course. (Everything here is just an
int.)
You will notice that statements do NOT end in a semicolon or anything
else! A single line = a single statement.
'''
 
x = 10
x *= 2
y = x + 3
 
# Use the print statement to... print things.
print("----- DEFINITIONS -----")
print(x)
print(x,y)
print() # Print with no arguments does an empty line.
 
'''
Function definitions use the "def" keyword. The standard Python syntax
is that a colon marks the beginning of a block (on the next line).
 
One truly innovative syntactic idea in Python is that WHITESPACE
MATTERS! Every line in a block must be indented the same amount of
whitespace. If your text editor automatically converts spaces to tabs,
use caution, because they are not the same to the Python interpreter.
 
Although the whitespace for indentation can be any amount (as long as it
is consistent), the official standard is to use 4 spaces (NO TABS!) for
each indentation level.
'''
 
def fun(x):
    return x + x*3
 
print(fun(12))
print(fun(fun(y)))
print()
 
'''
Python has lexical scope and functions are first-class. We can define
functions within functions, return functions from functions, and there
is even lambda for anonymous functions!
'''
 
def make_counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment
 
C = make_counter()
print(C(), C(), C(), C())
 
'''
Notice something odd in the function above? The "nonlocal" keyword
indicates that the name "count" should not be a local variable to
increment(), but rather should use the pre-existing local variable from
make_counter(). The reason we have to do things like this is that Python
doesn't distinguish syntactically between variable declaration and
re-assignment. By default, the first use of a variable within a scope
makes a declaration. The "nonlocal" overrides this behavior.
 
There is a similar keyword "global" that can be used to indicate
variables should have global scope instead of local.
'''
 
fun_alt = lambda y: y + y*3
print(fun(7), fun_alt(7))
 
print()
 
##### DATA TYPES #####
print('----- DATA TYPES -----')
 
'''
Python includes a number of built-in data types such as int, float,
list, tuple, and dict. To learn about their built-in operations, you can
type something like "help(int)" inside the interpreter to get the full
documentation. 
 
You can also covert between many of the built-in types; to do so, just
use the name of the type as a function. Let's start with numbers.
'''
 
print(float(20))
print(int(13.5))
 
# Most arithmetic operators work like you're used to.
print(1+2*3-4)
 
# The division operator / always does EXACT division
# To do integer division (quotient), use //
print(4/3, 4//3)
 
# Exponentiation is built-in using the ** operator.
print(3**2)
 
# The "mod" operator is what you're used to, but there is also a special
# global function divmod that produces the quotient and remainder
# at the same time.
print(28//5, 28%5)
print(divmod(28,5))
 
print()
 
'''
Booleans are pretty straightforward. True and False are the
literals, and you can do "and", "or", and "not".
'''
 
print(True, False, 3<5, True and True or not False)
print()
 
'''
Lists are an extremely important data type. You create lists with square
brackets, and can manipulate them in all sorts of wonderful ways. (Run
help(list) to see more!)
'''
 
L=[]
print(L, len(L)) #len is an extremely useful global function!
 
L=[1,2,3,4]
L.append(5)
print(L, len(L))
 
L.sort()
print(L)
L = [5,3,1]
print(sorted(L), L) 
# sorted just returns a sorted copy, whereas sort modifies the original.
 
L.extend(['types','can','be','mixed'])
L[1] = 'CHANGED!'
print(L)
print(['lists','can'] + ['be','added'])
 
# Besides the usual access like L[1], you can also use negative numbers
# to access from the back of the array.
print("First element is", L[0])
print("Last element is", L[-1])
# And you can get ranges using the "slice" notation with a colon.
print("First 2 elements are", L[:2])
print("Last 2 elements are", L[-2:])
print("Middle 2 elements are", L[2:4])
 
print()
 
'''
Tuples are like lists, except that they are immutable. They can be
quickly defined using parentheses. This can be slightly awkward since
parentheses are also used to override precedence. To make a one-element
tuple, you have to throw in an extra comma.
'''
 
T = (1,2,3)
print(T, len(T)) # len works for just about anything.
print(T + (4,5) + (6,))
 
# Notice the extra parens below.
# sorted always returns a list, even if its input is something else.
print( sorted((9,8,7)) )
 
print()
 
'''
Dictionaries are your basic hash map. You create them with curly
brackets. You can use the square brackets on a dictionary to insert or
retrieve elements.
'''
 
D = { 
    'key': 'value', 
    'another key': 'another value',
    5: ['types','can','mix'] 
}
 
print(len({}), len(D))
 
print(D['key'], D[5])
D[20] = 7
D.pop('another key')
print(D)
 
# The "in" operator can be used to see if a key is there.
print(20 in D)
print(5 in D)
print('value' in D)
 
print()
 
##### CONTROL STRUCTURES ####
print('----- CONTROL STRUCTURES -----')
 
'''
if and if/else statements are fairly normal. You will notice the special
keyword 'elif' to do an else-if case.
'''
 
if 1 < 4:
    print('1 is less than 4')
 
if False:
    print('Not here!')
else:
    print('Here instead!')
 
if 1 == 2:
    print('no')
elif 2 == 2:
    print('yes')
else:
    print('no')
 
print()
 
'''
while loops are just like you would expect. Like if's, no parens are
needed around the conditional.
'''
 
L=['a']
while len(L) < 5:
    L = L + L
print(len(L), L)
 
print()
 
'''
for loops are a little different. The only kind of for loop in Python is
a for-each loop to loop over all the items in some kind of "iterable"
collection.
'''
 
for a in [5,3,1]:
    print("For loop fun", a)
 
# "range" makes a range to loop over.
# This is how you do a typical for loop
for i in range(5, 10):
    print(i,end=' ') # this makes it end with space not newline
 
# Of course you can convert a range to a list.
# And the third argument to range changes the "increment" value.
print(list(range(10)))
print(list(range(5, 10, 2)))
print(list(range(10, 5, -1)))
 
# You can loop over JUST ABOUT ANYTHING YOU WANT
 
# remove the l's from hello
noels=''
for x in "hello":
    if x != 'l':
        noels = noels+x
print(noels)
 
for k in {1:2, 3:4}:
    print('The key is', k)
 
print()
 
##### LIST COMPREHENSIONS #####
print('----- LIST COMPREHENSIONS -----')
 
'''
List comprehensions are an awesome and special feature of Python that
lets you make a list a fill it up with the contents of anything that is
iterable. It is a very powerful and convenient syntax. The basic idea is
to write [(some expression) for (name) in (iterable)].
Let's see some examples!
'''
 
print([x for x in range(4)])
print(['really ' + s for s in ('I', 'like', 'Python')])
 
# zip is a useful utility to iterate over the tuples choosing one from
# each input list.
L1 = [4,5,6]
L2 = [7,8,9]
print([a*b for a,b in zip(L1,L2)])
 
# There is also a "map" function in Python to do something similar
print(list(map(len,['help','me','rhonda'])))
 
# You can add conditionals to the list comprehension for awesomeness!
# (This makes a list with all multiples of 3.)
print([x for x in range(20) if x % 3 == 0])
 
print()
 
##### GENERATORS #####
print('----- GENERATORS -----')
 
'''
You can make your very own "iterable" type of thing with a generator
function. The idea is that you replace a "return" statements with
"yield" statements, and then your function will keep going to yield more
and more things. Get excited for this one!
'''
 
def longwords():
    with open('/usr/share/dict/words', 'r') as English:
        # By the way, that's how you open a file for reading.
        for word in English:
            # By the way, that's how you loop over the lines in a file.
            word = word.strip()
            # This strips trailing whitespace.
            if len(word) > 18 and "'" not in word:
                yield word
 
# Now we can loop over this FUNCTION like it's any other iterable thing
for w in longwords():
    print(w)
 
# You can also get things out of an iterable manually, without a forloop.
gen = longwords()
print("The first long word is", next(gen))
print("The second long word is", next(gen))
 
print()