Today: string in/not-in, foreach, start lists, how to write main()
See "string4" on server - examples of features below: "foreach" and "in"
>>> 'c' in 'abcd' True >>> 'bc' in 'abcd' True >>> 'bx' in 'abcd' False >>> 'A' in 'abcd' False
The form not in inverts the in test, True if the small thing is not in the big thing. Say for example we have a string of bad_chars, and we want to print a char if it is not bad. Using the "not in" form, the code reads very nicely.
if ch not in bad_chars:
print(ch)
We could use regular "in", and then add a "not" to its left, like the following form. This works, but the above form is the preferred style and reads better.
if not ch in bad_chars:
print(ch)
In Python 'a' and 'A' are not equal, and so 'apple' and 'Apple' are two different strings. This is called "case-sensitive", and it is the default behavior in Python. If a problem does not state anything about case-sensitivity, assume case-sensitive, which is generally the easier form to compute.
If an algorithm does extra work to treat 'a' and 'A' the same, that is called the "case-insensitive" approach, and it is generally more work. If we want your code to compute something case-insensitive, we will always say so explicitly in the problem description.
for ch in s:
# use ch in here,
# will be one char from s
Like earlier double_char, but using foreach.
Solution
def double_char2(s):
result = ''
for ch in s:
result = result + ch + ch
return result
Demonstrates both foreach and in
intersect(a, b): Given two strings, a and b. Return a version of a, including only those chars which also appear in b. Use a case-sensitive comparison. Use a for/ch/s loop.
Solution
def intersect(a, b):
result = ''
# Look at all chars in a, check
# each using "in"
for ch in a:
if ch in b:
result += ch
return result
See the guide: Python List for more details about lists
See the "list1" examples on the experimental server
[1, 2, 3]Use square brackets [..] to write a list in code (a "literal" list value), separating elements with commas. Python will print out a list value using this same square bracket format.
>>> lst = ['a', 'b', 'c', 'd'] >>> lst ['a', 'b', 'c', 'd'] >>>
"empty list" is just 2 square brackets with nothing within: []
len(lst)Use len() function, just like string. As a nice point of consistency, many things that work on strings work the same on lists - they are after all both linear collections using zero-based indexing.
>>> len(lst) 4
Use square brackets to access an element in a list, like string again (bad index err possible). Valid index numbers are 0..len-1.
>>> lst[0] 'a' >>> lst[2] 'c' >>> lst[9] Error:list index out of range
The big difference from strings is that lists are mutable - lists can be changed. Elements can be added, removed, changed over time. We'll look at four list features.
# 1. make empty list, then call .append() on it >>> nums = [] >>> nums.append(1) >>> nums.append(2) >>> nums.append(3) >>> >>> lst [1, 2, 3] >>> len(lst) 3 >>> lst[0] 1 >>> lst[2] 3 >>> # 2. Similar, using loop/range to call .append() >>> nums = [] >>> for i in range(6): ... nums.append(i * 10) ... >>> nums [0, 10, 20, 30, 40, 50] >>> len(nums) 6 >>> nums[5] 50
See the "list1" section on the experimental server.
list_n(n): Given non-negative int n, return a list of the form [0, 1, 2, ... n-1]. e.g. n=4 returns [0, 1, 2, 3] For n=0 return the empty list. Use for/i/range and append().
Solution
def list_n(n):
nums = []
for i in range(n):
nums.append(i)
return nums
>>> lst = ['a', 'b', 'c', 'd'] >>> 'c' in lst True >>> 'x' in lst False >>> 'x' not in lst # preferred form to check not-in True >>> not 'x' in lst # equivalent form True
>>> lst = ['a', 'b', 'c', 'd'] >>> for s in lst: ... # use s in here ... print(s) ... a b c d
>>> lst = ['a', 'b', 'c', 'd']
>>> lst.index('c')
2
>>> lst.index('x')
ValueError: 'x' is not in list
>>> 'x' in lst
False
>>> 'c' in lst
True
donut_index(foods): Given "foods" list of food name strings. If 'donut' appears in the list return its int index. Otherwise return -1. No loops, use .index(). The solution is quite short.
Solution
def donut_index(foods):
if 'donut' in foods:
return foods.index('donut')
return -1
list_censor(n, censor): Given non-negative int n, and a list of "censored" int values, return a list of the form [1, 2, 3, .. n], except omit any numbers which are in the censor list. e.g. n=5 and censor=[1, 3] return [2, 4, 5]. For n=0 return the empty list.
Solution
def list_censor(n, censor):
nums = []
for i in range(n):
# Introduce "num" var since we use it twice
# Use "in" to check censor
num = i + 1
if num not in censor:
nums.append(num)
return nums
As your algorithms grow more complicated, with three or four variables running through your code, it can become difficult to keep straight in your mind which variable, say, is the number and which variable is the list of all the numbers. Many little bugs have the form of wrong-variable mixups like that.
Therefore, an excellent practice is to name your list variables ending with the letter "s", like "nums" above, or "urls" or "weights". Then when you have an append, or a loop, you can see the singular and plural variables next to each other, reassuring that you have it right.
url = (some crazy computation)
urls.append(url)
Or like this
for url in urls:
STATES = ['CA, 'NY', 'NV', 'KY', 'OK']
# provided ALPHABET constant - list of the regular alphabet
# in lowercase. Refer to this simply as ALPHABET in your code.
# This list should not be modified.
ALPHABET = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
...
def foo():
for ch in ALPHABET: # this works
print(ch)
If we get through this on Fri fine, otherwise we'll do it monday.
For details see guide: Python main() (uses affirm example too)
affirm.zip Example/exercise of main() command line args. You can do it yourself here, or just watch the examples below to see the ideas.
First run the code, see what the command line arguments (aka "args") do:
-affirm and -hello options (aka "flags")
$ python3 affirm.py -affirm Lisa Everything is coming up Lisa $ python3 affirm.py -affirm Bart Looking good Bart $ python3 affirm.py -affirm Maggie Today is the day for Maggie $ python3 affirm.py -hello Bob Hello Bob $
-affirmThe command line arguments, or "args", are the extra words you type on the command line to tell the program what to do. The system is deceptively simple - the command line arguments are just the words after the program.py on the command line, separated from each other by spaces. So in this command line:
$ python3 affirm.py -affirm Lisa
The words -affirm and Lisa are the 2 command line args.
args Python ListWhen a Python program starts running, typically the run begins in a special function named main(). This function can look at the command line arguments, and figure out what other functions to call.
In our main() code the variable args is set up as a Python list containing the command line args.
$ python3 affirm.py -affirm Lisa
....
e.g. args = ['-affirm', 'Lisa']
$ python3 affirm.py -affirm Bart
....
e.g. args = ['-affirm', 'Bart']
For this example, say we have functions print_affirm(name) and print_hello(name) which are already written. The main() function will look at the args and call the appropriate functions. The key pattern is that main() can call functions, passing in the right data as their parameters.
Functions to call:
def print_affirm(name):
"""
Given name, print a random affirmation for that name.
"""
affirmation = random.choice(AFFIRMATIONS)
print(affirmation, name)
def print_hello(name):
"""
Given name, print 'Hello' with that name.
"""
print('Hello', name)
def print_n_copies(n, name):
"""
Given int n and name, print n copies of that name.
"""
for i in range(n):
# Print each copy of the name with space instead of \n after it.
print(name, end=' ')
# Print a single \n after the whole thing.
print()
Make this command line work, editing the file affirm-exercise.py:
$ python3 affirm-exercise.py -affirm Lisa
Solution code
def main():
args = sys.argv[1:]
....
....
# 1. Check for the -affirm arg pattern:
# python3 affirm.py -affirm Bart
# e.g. args[0] is '-affirm' and args[1] is 'Bart'
if len(args) == 2 and args[0] == '-affirm':
print_affirm(args[1])
Write if-logic in main() to looking for the following command line form, call print_hello(name), passing in correct string.
$ python3 affirm-exercise.py -hello Bart
Solution code
if len(args) == 2 and args[0] == '-hello':
print_hello(args[1])
In this case, the function to call is print_n_copies(n, name), where n is an int param, and name is the name to print. Note that the command line args are all strings.
$ python3 affirm-exercise.py -n 10000 Hermione