I am following https://automatetheboringstuff.com/2e/chapter1 CHAPTER 1 AND OVERALL OBSERVATIONS. Download Python from Python.org and mu from https://codewith.mu/en/download . For me the latest version of mu does not work on my mac. In chapter0, it says how to figure out exactly whether you have a 64-bit or 32-bit OS. There are a couple different ways to run Python. In terminal, do python3 . You can then do stuff line by line. Anything after # is a comment. 2+3 7*5 12 // 2.2 # just the integer part of the division. 12 % 2 # just the remainder. 12 % 2.2 # does weird stuff. 4 ** 3 # exponents. (4+2)*(3+2) If you have a module called printie.py, you can also do python3 printie.py >> output.txt to save output to a file called output.txt. Alternatively, you can use IDLE. In IDLE, I went to IDLE -> Preferences -> Keys and chose history-previous and history-next and set them to up arrow and down arrow. You can go line by line in the IDLE Shell too. Often code will run correctly in IDLE but not in terminal, because of the spacing and tabs involved. If you want to write a program to do multiple things, and maybe take input from the user and then output something, it is very hard to do it in terminal. In IDLE you just do file -> open to load in the file and then do run -> run module. When running modules though, if you say 2+3 it does nothing. You have to say print(2+3) or it won't output the result. You can also say x = 2+3 to store the result. Two notes about Python. The indentation thing makes python very inflexible. It's unusual how you cannot end functions and for loops with brackets but instead need returns. Here is a little module to try in Python. print('Hello, world!') print('What is your name?') myName = input() print('It is good to meet you, ' + myName) print('The length of your name is:') print(len(myName)) print('What is your age?') myAge = input() print('You will be ' + str(int(myAge) + 1) + ' in a year.') Now here is a little module to illustrate how the command line is not nice for multiple line operations. x = True if x: print(2+4) You need the indentation. If you try to copy and paste these lines into the shell it won't work. You will get a "SyntaxError: multiple statements found while compiling a single statement". += works as in C. x = 2 x += 1 ## 3. Python has wonderful syntax for dealing with strings. For example, if you say x = 'Alice' + 'Bob' print(x) it does just what you want, unlike R. The book always uses single quotes for strings, but doublequotes work too. x = "Alice" * 5 len() is the length of a character string. str() converts a number into a string. x = str(5) int is weird. int('4') works but int('4.2') doesn't. float() works nicely. int(4.2) int("4.2") float(4.2) float('4.2') x = float("4.2") x * 7 CHAPTER 2. Like in C, the comparison operators are ==, !=, >= etc. and, or, and not are logical. You don't seem to need parentheses with if, in Python. if statement else: You have to have a colon and an indented block of code on the NEXT line. elif is only executed if the preceding thing was false. mynum = int(input()) if mynum < 5: print("Your number is small") elif mynum < 7: print("Your number is medium") elif mynum <= 8: print("Your number is large") else: print("Your number is huge") While loops are quite intuitive. You can use break to stop the loop. i = 1 while(i < 10): print("Your number is ", i,".\n") if i == 7: break i = i + 1 CTRL-C stops an infinite loop. continue makes it go back to the beginning of the while loop. We will mostly use for loops. In a for loop, continue will pass to the next value of i. for i in range(10): print("Your number is",i,"\n") print("Now let's try it with continue\n") for i in range(10): if i == 5: continue print("Your number is",i,"\n") The range can also go backwards, or by any step you want. for i in range(20,3,-2): print("your number is ",i) There are some modules ready for you to use by calling import. For example in random there is a function random.randint to generate a random integer between import random, sys, os, math ## Modules print(random.randint(1, 10)) This is a guess the number game. import random secretNumber = random.randint(1, 20) print('I am thinking of a number between 1 and 20.') # Ask the player to guess 6 times. for guessesTaken in range(1, 7): print('Take a guess.') guess = int(input()) if guess < secretNumber: print('Your guess is too low.') elif guess > secretNumber: print('Your guess is too high.') else: break # This condition is the correct guess! if guess == secretNumber: print('Good job! You guessed my number in ') print(str(guessesTaken) + 'guesses!') else: print('Nope. The number I was thinking of was ') print(str(secretNumber)) It is sometimes useful to change directories in Python and load a module. See https://note.nkmk.me/en/python-os-getcwd-chdir for tips on changing directories. See https://realpython.com/run-python-scripts/#scripts-vs-modules for tips on running scripts and modules. import os os.getcwd() os.chdir("/Users/rickpaikschoenberg/Desktop") import module1 CHAPTER 3. Functions. Python has its own unique syntax for functions. Here are some simple examples. def mynumb(): print("What is your number?") i = input() print("Your number is ",i) mynumb() You need the return after the function for python to know it is over. You need () after def mynumb so it knows it is a function. If a function like print is void and returns nothing, what it actually returns is the value None. Variables defined in functions are all local by default. To change a global variable within a function, do global x def f(): global y y = 3 y = 2 print("y is", y) f() print("y became", y) ## it will output 3. try and except are sometimes useful. The code that could potentially have an error is put in a try clause. When code in a try clause causes an error, the program execution immediately moves to the code in the except clause. After running that code, the execution continues as normal. def spam(divideBy): try: return 42 / divideBy except ZeroDivisionError: print('Error: Invalid argument.') print(spam(2)) print(spam(12)) print(spam(0)) print(spam(1)) The book gives an example where you have a while loop and if someone hits ctrl-c it ends the program using sys.exit(). import time, sys indent = 0 # How many spaces to indent. indentIncreasing = True # Whether the indentation is increasing or not. try: while True: # The main program loop. print(' ' * indent, end='') print('********') time.sleep(0.1) # Pause for 1/10 of a second. if indentIncreasing: # Increase the number of spaces: indent = indent + 1 if indent == 20: # Change direction: indentIncreasing = False else: # Decrease the number of spaces: indent = indent - 1 if indent == 0: # Change direction: indentIncreasing = True except KeyboardInterrupt: sys.exit() CHAPTER 4, lists. Lists are very easy to use and manipulate in Python. Unlike R, they are indexed by 0 as in C. Like vectors in R, you can use one square bracket to number the items, but like lists in R, you can different types of objects inside your list. Try this for example. x = [1,2,5] print(x[0]) ## 1. x = [1,2,[10,11,12]] print(x[2][1]) ## 11. print(x[-1]) ## means the last element of x. print(x[0:2]) ## means x[0] and x[1]. It does not include x[2]. This is called a slice. With lists, you can do + and *. You can also use "in" and "not in". They are easy to use. a = [1, 2, 3] + ['A', 'B', 'C']; print(a) a = [1,2,8] * 4; print(a) ## [1, 2, 8, 1, 2, 8, 1, 2, 8, 1, 2, 8] print(a) del a[2] ## removes the 3RD element of a. print(a) x = 4 in a; print(x) x = 4 not in a; print(x) x = 8 not in a; print(x) a = [1,2,2]; print(a) size, age, hair = a; print("\n a = ", a, "\n size = ", size, "\n age = ", age) enumerate stores a pair of values. The first is the index and the second is the value. supplies = ['pens', 'staplers', 'flamethrowers', 'binders'] for index, item in enumerate(supplies): print('Index ' + str(index) + ' in supplies is: ' + item) Once you load the "random" module, using import, random.shuffle is the same as sample() in R, and random.choice picks one element at random. Note that random.shuffle does not create a new vector with the items in a different order. So if you do b = random.shuffle(supplies); print(b) then b is empty so it prints "None". Instead, it permutes the items in the list supplies itself! import random supplies = ['pens', 'staplers', 'flamethrowers', 'binders']; print(supplies) a = random.choice(supplies); print(a) b = random.shuffle(supplies); print(b) print("The order is now " + supplies) Methods. A method, like "index" in x.index, is a function that acts on the object before the period. So it should be thought of as index(x). Unlike R functions though, usually methods change the object x though, rather than outputting a new object. x = [1,2,1,5,6]; print(x) x.append(5); print(x) ## makes it 1,2,1,5,6,5. x.insert(1,7); print(x) ## makes it 1,7,... x.remove(1); print(x) ## removes the first instance. x.remove(5); print(x) x.reverse(); print(x) ## reverses the order. x.sort(); print(x) y = x.index(1); print(y) ## index of 1st time 1 appears. y = x.index(5); print(y) ## These methods only work on lists, and they act on the lists. If you do y = x.sort(), the sort method acts on x, but essentially the output is void, so y is void. I stopped here last time. I have some announcements. -- Attendance is mandatory at your own day plus at least 1 of the 2 other days. -- No class Mon Nov21! -- See lecture7notes.txt for the project order. -- Plan to be back in person for all of these days including Wed Nov23 unless you hear otherwise from me by Tue Nov 22 at noon. -- Assuming we are in person, email me your pdf or ppt of your slides by the night before your presentation, and then you will use my computer for your presentation. x = [1,2,1,5,6] y = x.sort(); print("at first y is ", y) ## produces "None"! x.sort; y = x; print("\n Now it works and y is ", y) You can also use the sort method to sort character strings. By default it puts capitals before lower case. For sorting in regular alphabetical order use the argument key = str.lower . x = ["s","P","e","L","l"]; print(x) x.sort(); print(x) x.sort(key=str.lower); print(x) You can split up a single instruction across multiple lines using the \ line continuation character at the end. x = 1 + \ 2 + 3 print(x) Sequence data types. Python is fantastic about allowing you to refer to string elements very naturally. Python sequence data types include lists, strings, range objects returned by range(), and tuples. You can act on these the way you do with lists. x = range(6,10); print(x) print(x[0]) print(x[1]) print(x[2]) print(x[3]) print(x[4]) x = "chicken"; print(x) print(x[0]) print(x[-1]) y = "i" in x; print(y) However, in Python, strings are immutable. You can't do x[2] = "u". You have to instead do newx = x[0:2] + "u" + x[3:7] Remember that 0:2 means just 0 and 1, and 3:7 means 3-6. x = "chicken"; print(x) newx = x[0:2] + "u" + x[3:7]; print(newx) Tuples. Tuples are just like lists but have ( instead of [. And tuples are immutable. x = [1,2,3]; print(x) print(x[1]) x[1] = 7; print(x) x = (1,2,3); print(x) print(x[1]) x[1] = 7 You can use y=tuple(x) or y=list(x) to convert an object to that type. x = (1,2,3); print(x) y = list(x); print(y) y[1] = 7; print(y) print(x) IN PYTHON, LISTS ARE STORED AS REFERENCES! So if you do y = x, and x is a list, then y is actually a reference to the same list, and if you change y you will change x. This is not true with tuples though. x = [1,2,3,4,5]; print(x) y = x; print(y) y[2] = 12; print(y) print(x) x = (1,2,3,4,5) y = list(x) z = list(x) y[2] = 12 print("x is ",x) print("y is ",y) print("z is ",z) ## still 1,2,3,4,5. Use copy.copy(x) to make a copy of x with a different reference. So now if you change the copy it will not change x. Use copy.deepcopy(x) if the list contains other lists. import copy x = [1,2,3,4,5]; print(x) y = copy.copy(x); print(y) y[1] = 10; print(y) print(x) print("x is ", id(x)) print("y is ", id(y)) ## they are different references now! y = x print("y is ", id(y)) CHAPTER 5. Dictionaries. A dictionary is a list indexed by general keys, instead of integers. Use curly brackets for dictionaries. The elements in a dictionary are not ordered. If you want the keys ordered, you can do list(x). x.keys(), x.values(), and x.items() are lists. x.get("house",0) will be 12 if house is in x or 0 otherwise. x.setdefault("color",3) ## sets color to 3 only if color's not already in there. x.items() is useful when you want to loop through all the keys. x = {"house": 12, "car": 7, "shirt": 14, "bicycle": -2}; print(x) y = x["bicycle"]; print(y) y = list(x); print(y[1]) print(x.keys()) print(x.values()) print(x.items()) ## both y = x.items(); print(y) y = x.get("house",0); print(y) x.setdefault("color",3); print(x) for a,b in x.items(): print("Key: " + a + " Value: " + str(b)) At the end of ch5, Zweigart has a nice module to tabulate the characters in a character string using dictionaries and the pprint module. import pprint message = 'It was a bright cold day in April, and the clocks were striking \ thirteen.' count = {} for character in message: count.setdefault(character, 0) count[character] = count[character] + 1 print(count) pprint.pprint(count) CHAPTER 6. Strings. Python has a lot of features making it very easy and natural to manipulate strings. \ is an escape character, so \" makes quotes appear in a string. \' = '. \t = tab. \n = newline. \\ = \. r makes something a raw string. Backslashes will appear. Useful for directories. You can use r" to make a raw string, which ignores escape characters, so the string has slashes but will look like single slashes when printed. This is useful for addresses of directories on a computer. x = "He said \"It\'s mine!\""; print(x) x = "21 \\ 3 = 7."; print(x) x = r"Users\Desktop\myfolder" print(x) Multiline strings. Use """ to start and stop multiline strings. Newlines, tabs, and even quotes are saved correctly. This is a bit like verbatim in latex. x = """ Know me as you might, By the fire shining bright. Know me by the bed where we've lain. You can know me as you might If just for one night You'll know me by no other name.""" print(x) String interpolation. % is useful. This is a bit like Rprint in C. name = "Rick" age = 51 x = "My name is %s. I am %s years old." % (name, age) print(x) You can also use f before the quotes, to make an f string. These are the same but use braces instead of %s. name = "Rick" age = 51 x = f"My name is {name}. Next year I will be {age + 1}." print(x) upper() makes a character string all upper case. This is extremely useful especially for comparing two strings to see if they are identical. Just change everything to upper or lower case first. name = "David" print(name) name2 = name.upper() print(name2)