names = ['Asha', 'Michael', 'Arjun', 'Roland']
type(names)
list[i] refers to the ith element of list (where the count starts at 0). We can use this value and we can also change this value.
print("the element at 1 is ", names[1])
names[1] = 'Victoria'
print(names)
We can use negative indexing to access list elements counting from the end of the list.
print(names[-1])
print(names[-2])
The +
operator adds two lists together.
L1 = [1, 2, 3]
L2 = ['a', 4, 5]
L = L1 + L2
print(L)
# but you can't add a single item to a list with +
wrong = L1 + 6
Because lists are objects, we can call methods on a list. One method, append
takes a single parameter and adds it to the end of a list.
names.append('Golnaz')
print(names)
Another method from the list class is sort
. Sort works in place and
changes the list. It returns None
which is a special value in Python
like null
.
names.sort()
print(names)
A method is very like a function, except that it acts on a particular object. It is as if we are telling the list to sort itself.
We can use special syntax to take a section of a list or to insert one list into another.
fruit = ['Apples', 'Oranges', 'Pears', 'Bananas']
print(fruit[2:4])
print(fruit[1:-1])
print(fruit[:3])
last_fruit = fruit[-1:]
print(last_fruit)
Notice that negative indexing can be used. Notice that a : on either side of the comma gets that end of the list. Notice that even though the last list contains only one element, it is still a list.
We can also assign a list to a slice. This replaces the slice with the new list. The slice you replace and the replacement slice don't have to have the same number of elements. That means you can use splicing to increase or decrease lists.
# if the two list are the same size, it does as expected and just replaces them
fruit[1:3] = ['Navel Oranges', 'Anjou Pears']
print(fruit)
# but if you replace with an empty list, it removes items
fruit[2:3] = []
print(fruit)
# or you could replace a slice with a longer list
fruit[1:3] = ['beets', 'carrots', 'peppers', 'cabbage']
print(fruit)
# or you could replace an empty slice even
fruit[1:1] = ['chocolate']
print(fruit)
# notice that assigning a list to a slice of length 1
# is different than assigning a list to a single element
fruit[2] = ['X', 'Y']
print(fruit)
SHORT PRACTICE TIME
The most common way to loop over a list is to use a loop like the following:
numbers = [7, 8, 42, 10, 5]
for item in numbers:
print(item)
Let's do a really easy task, just to make sure everyone is with me here. Use this type of loop to add up the total of all the numbers in our list and then print the total.
sum = 0
for item in numbers:
sum = sum + item
print("The sum is", sum)
Now, change your code to sum the squares of the numbers (and while you are at it, print each square out.)
sum = 0
for item in numbers:
square = item * item
print("square of", item, "is", square)
sum = sum + square
print("The sum is", sum)
Now change your code again to save the square of each element into the list. Does it work with this loop?
for item in numbers:
square = item * item
print("square of", item, "is", square)
item = square
print(numbers)
The elements were squared but the resulting squares were not saved in the list. That's because the variable item
is not a pointer to an element in numbers
but simply is assigned a copy of value of each element of numbers on each iteration.
We need a different sort of loop if we want to change the elements of the list.
numbers = [3, 5, -1, 0]
for i in range(len(numbers)):
print(numbers[i])
numbers[i] = numbers[i] * numbers[i]
print(numbers)
It is actually a little more complicated, but you can think of range (when called with a single integer parameter i
) as generating a list of the integers from 0 up to but not including i
.
for i in range(5):
print(i)
So range(len(some_list))
is perfect for looping over the indices of the list elements in order.
SHORT PRACTICE TIME
Let's use the append
method that we saw earlier and the input
function to ask the user for 5 integers and then create a list with those
elements. Then let's loop over the list and print out the values of the list that are larger than their indices.
Before we start, you need to know one more thing. You can create an empty list using the square brackets and no elements and appending to an empty list creates a list with just the one item.
days = []
days.append("monday")
print(days)
numbers = []
We can create an empty list by using the square brackets with no items. Now add one input statement to ask for the integer.
numbers = []
new_number = input("please enter an integer ")
Then append that integer we just received to our list.
numbers.append(new_number)
Now repeat this asking and appending 5 times by using a for
loop.
numbers = []
for i in range(5):
new_number = input("please enter an integer ")
numbers.append(new_number)
print (numbers)
But this isn't right. We wanted integers and we have strings. Remember that the values from the function input are always strings. If we want them to be converted to integers, we call the function int
.
numbers = []
for i in range(5):
new_number = int(input("please enter an integer "))
numbers.append(new_number)
print (numbers)
Now we need to iterate over the list and print only the items that are
larger than their index. Since we need to know the index, we need to use the i in range(len ...
loop
for i in range(len(numbers)):
if numbers[i] > i:
print(numbers[i])
We've used strings a bit as a type already. Let's talk a bit more about strings.
Strings are not simply lists of characters. There are some extra methods that apply to strings and there are some list methods that don't apply to strings. But many things that worked for lists, work for strings.
For example, we access individual elements of a string with [index]
name = "Michelle"
print(name[2]) # counts from 0
print(name[-1]) # negative indexing works
print(name[-3:]) # slicing works
Assigning to a string element is not allowed.
name = 'michelle'
name[0] = 'M'
Slicing also is not allowed.
name = 'michael'
name[-3:] = "elle"
first = 'santa'
last = 'clause'
print(first + last)
name = first + " " + last
print(name)
empty = ""
print(empty)
print(empty + "a")
We can use both kinds of loops over strings.
disease = "Typhoid"
for ch in disease:
print(ch)
for i in range(len(disease)):
print(disease[i])
Use the for ch in s
form of the loop when you can --- when you don't need to know the index of a character inside the loop.
It turns out that we don't often have to loop over strings in our own programs, because strings are objects and there are methods provided in the string class for many of the things we would want to do.
Like lists, strings are also objects and have methods. One difference, though is that while some list methods (like sort and append) change the list, none of the string methods ever change a string.
So what good are they?
Like functions, methods can return a value. Many of the string methods, return another string. For example:
s = "hello"
t = s.upper()
print (s, t)
Notice that the string s
hasn't changed. But calling the method upper
on string 's'
, returned the string 'HELLO'
which we assigned to variable t
. Here is another example.
food = " Pad Thai "
fixed_food = food.strip()
print ("|",food, "|", fixed_food)
Notice that the print function inserted one space for each comma and that the function strip
remove the leading and trailing spaces from our string food
.
line = "something\n"
cleaned_line = line.strip("\n") # we can string a specific character
print(cleaned_line)
value = ",15,"
value = value.rstrip(',') # or use lstrip or rstrip to only strip from one end
print(value)
To tokenize a string into a list, use the method split()
s = "The quick brown fox."
tokens = s.split() # called with no parameter, it splits on whitespace
print(tokens)
line = "14,6,fred,male".split(',') # or you can specify the delimiter (separator)
print(line)
There are quite a lot of string methods and you can find the list in the online python documentation at https://docs.python.org/3/library/stdtypes.html#string-methods
The operator in
is used to return a boolean indicating if a character is in a string
or an object is in a list.
VOWELS = """aeiouAEIOU"""
"$" in VOWELS
"A" in VOWELS
colours = ['red', 'blue', 'green', 'yellow']
'red' in colours
'grey' in colours
'Yellow' in colours # match is case sensistive
SHORT PRACTICE TIME (2 questions -- but you may only have time for 1)
Q1: Let's assume we have a list of strings that are supposed to be all in uppercase. But some errors got into the data and there are a few strings in the list that are not completely uppercase letters. Write Python code that prints out the elements of the list that are not all in uppercase. Hint: look at the string methods that are available.
original_list = ['AA', 'BB', 'oops', 'DD', 'xx']
for item in original_list:
if not item.isupper():
print(item)
Q2: Write code that takes a list of strings and doesn't change the list. Instead create a new list that only contains the strings from the original list that contain only digits.
original_list = ['98', 'a', '5']
result = []
for item in original_list:
if item.isdigit():
result.append(item)
print("original is still:", original_list)
print("resulting list:", result)
We've used functions quite a bit already. The syntax for defining functions in Python is easy. Let's put the solution to the two practice problems above into functions.
def only_digits(original):
""" (list of str) -> list of str
Return a new list that consists of the elements of original that are all digits
"""
result = []
for item in original_list:
if item.isdigit():
result.append(item)
return result
original_list = ['98', 'a', '5']
L = only_digits(original_list)
print(original_list)
print(L)
Things to note
def
keyword then function namehelp(<function name>)
return
keywordhelp(only_digits)
In the example above, we returned a new list and did not modify the original. But it is possible to modify a list in a function by assigning to its elements. Do this in the next exercise.
PRACTICE TIME
Q1. Write a function clean_up that takes a string and returns a new string that is the same as the old string except that all the punctuation has been replaced by spaces and any uppercase letters have been converted to lowercase. Use a constant PUNCTUATION
similar to the one we defined earlier.
def clean_up(original):
""" (str) -> str
Return a copy of original where all punctuation has been replaced by a space and
the string is converted to lowercase
"""
PUNCTUATION = "!@#$%^&*(){}[];:'<>,.?"
result = ""
for ch in original:
if ch in PUNCTUATION:
result += " "
else:
result += ch
return result.lower()
clean_up("Trudeau, Justin?")