Python Fundamentals 2#
Review and Outline#
Great Work! We have made it this far…we know some basic calculations, data types and structures (lists, tuples, strings, dictionaries), we also know how to get help ? and read Error: messages. Finally, we should be getting comfortable with the notebook and markdown.
Where are we going? In this notebooke we will cover some key operations: Comparisons, if else conditional operations, for loops. In the end, we will learn the core concept of object in object oriented programming and how it is used in python to help us better understand the language.
This notebook largely follows the discussion in the Book. Note, in the book there are many more excercises to try. Pleast try them at home.
Python Tools#
Boolean variables, comparisons, conditionals (if, else), slicing, loops (for), tab completion, function definitions and objects.
Buzzwords. Code block, data structures, list comprehension, PEP8.
Booleans#
Basic idea, make a comparison and the result is a true or false value. We call these bools…
test = 1 < 0 # This is a comparsition, value 1 versus zero....
print(test) # What does it return a True or False value...
print(type(test))
False
<class 'bool'>
KEY Note the type, it’s a bool or short for Boolean.
Here are some more operations…bools can be combined with integers and floats…
print(2*test)
# Now what if we had 1 < 0 above, what would the command return... note that it will
# give a zero... so what is going on here is implicitly with a True is the value 1
# and associated with the value False is a zero (note how in the background there is
# probably a dictionary doing this....)
test1 = 0.666666666666666666 # This is interesing, when are they equal...
test2 = 2/3
print(test1 == test2)
0
True
Some more operations… == is equal, >= greater than or equals, <= less than
or equals, != not equals. Keep these in mind. There are also other ways to take the oppisite value by using the not built-in
test = not 1 > 0 # this is not whatever 1 > 0 is, so not True which is FALSE
print(test)
False
Then notice what happens when we print a statement…
x = 2*3
y = 2**3
print('x greater than y is', x > y)
x greater than y is False
Exercise. What is 2 >= 1? 2 >= 2? not 2 >= 1? If you’re not sure, try them in the IPython console and see what you get.
Exercise. What is
print(2 + 2 == 4)
print(1 + 3 != 4)
Explain what is going on here….
Exercise What is
print("sarah" == 'Sarah')
Exercise. What do these comparisons do? Are they true or false? Why?
print(type('Sarah') == str) # IS it a string? YES!!!
print(type('Sarah') == int) # IS it an integer??? NO!
print(len('Sarah') >= 3) # Is the length longer than three? YES!
True
False
True
Comparisons in String
name1 = 'Chase'
name2 = 'Spencer'
check = name1 > name2
print("Is Chase > Spencer ",check) #hmmmm....
Is Chase > Spencer False
https://stackoverflow.com/questions/4806911/string-comparison-technique-used-by-python
Here is the quick run down, this does this thing in lexicographic ordering… this means: First the first two items are compared, and if they differ this determines the outcome of the comparison; if they are equal, the next two items are compared, and so on, until either sequence is exhausted. What determines the order…in this case note that “S” comes later in the alphabet than “C” thus is has a larger “value”, thus “Chase > Spencer” is false.
When comparing uppercase vs. lower case, uppercase come before lower case…The stuff like *& come before. How do I know exactly what is going on… here is a link to the unicode point ordering
https://en.wikipedia.org/wiki/List_of_Unicode_characters
And scroll down to the Latin Script /Basic Latin table there. There there is a number for each possible character. To see the number just type ord("z") and note how this should give back the value 122 and then look in the table it should have the value 122. In the comparison above, what it is doing is taking the number in this table for the given character and then comparing it to the number for the other character.
"z" > "a"
True
ord("!")
33
Conditional (If/Else)#
Now that we know how to tell whether a comparison is true or false, we can build that into our code. “Conditional” statements allow us to do different things depending on the result of a comparison or Boolean variable, which we refer to as a condition. The logic looks like this:
if a condition is true, then do something.
if a conditions is false, do something else (or do nothing).
if 1 > 0: # this statment checks the value, then IF TRUE it advances to the next line
print("1 is greater than 0") # here where it prints the value
print("test")
1 is greater than 0
test
Key issue, an if statement must always be followed by “:” and then the next line or lines associated with the statement must be indicated by 4 spaces. ONLY 4 spaces, Jupyter will do this automatically….there is also some kind of debate about spaces or tabs…here is some interesting info if you need to choose:
https://stackoverflow.blog/2017/06/15/developers-use-spaces-make-money-use-tabs/
x = 5 # we can change this later and see what happens
if x > 6:
print('x =', x)
print('Done!')
Done!
x = 7
condition = x > 6
if condition:
print('if branch') # do if true
print(condition)
else:
print('else branch') # do if false
print(condition)
if branch
True
Exercise. Take the names name1 and name2, both of them strings. Write a program using if and else that prints the name that comes first in alphabetical order. Test your program with name1 = ‘Dave’ and name2 = ‘Glenn’.
name1 = 'Dave'
name2 = 'Glenn'
Exercise Make it insensitive to capitalization…
Slicing#
This is important stuff to be comfortable with. When we start to work with Pandas (the data package), slicing will be a key skill to “slice” the data in the way that we want. For now we will work with strings and lists.
a = "some"
print([a[0], a[1], a[2]])
# Note how it is treating the string just like a tuple (remember python starts indexing from 0)
# so we are calling each individual character...
['s', 'o', 'm']
a[1] = "*" # can we re-assgin? # no...string is like a tuple where the object is immutable.
print(a)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[14], line 1
----> 1 a[1] = "*" # can we re-assgin? # no...string is like a tuple where the object is immutable.
2 print(a)
TypeError: 'str' object does not support item assignment
One of the interesting things about this is that there are both a forward counter and a backward counter. Here is an example:
print(a[-3]) # this should give an o, so 0 is s, -1 is e, -2, is m...
#print(a[-400]) # But it will not do this infinitly, it will do this untill it returns
# back to s or -4,
Exercise Take the string firstname = ‘Monty’ and write below it the forward and backward counting conventions. What integer would you put in square brackets to extract the third letter (n) under each system?
Exercise. Find the last letter of the string lastname = ‘Python’. Find the second to last letter using both the forward and backward counting conventions.
Exercise. Take the list numberlist = [1, 5, -3]. Use slicing to set a variable first equal to the first item. Set another variable last equal to the last item. Set a third variable named middle equal to the middle item.
Now how do we pull groups of objects out of a data structure. We use the : operator. What this does is when we have say [0:2] this will pull out the first element AND everything after it NOT including the object in the second position. That is the value after the colon is not included. LEts see this…
c = 'something'
print('c[1] is', c[1]) # We know this...
print('c[1:2] is', c[1:2]) # This says take between 1 and 2 NOT including 2 (so same as above)
print('c[1:3] is', c[1:3]) # This says take between 1 and 3 NOT including 3
print('c[1:] is', c[1:]) # This says give from postion 1 onward so omething...if -1?
print('c[1:-1] is', c[1:-1]) # This works, again, from postion 1 and -1 NOT including -1, so oemthin
Exercise. Set lastname = ‘Python’. Extract the string ‘thon’.
Exercise. Set numlist = [1, 7, 4, 3]. Extract the middle two items and assign them to the variable middle.
Exercise.
Extract all but the first item and assign them to the variable allbutfirst.
Extract all but the last item and assign them to the variable allbutlast.
allbutfirst = ''
allbutlast = ''
for Loop#
As with the conditional operation, this is a key skill. In particular, it allows for us to scale up the number of operations without having to constantly write code to perform each one.
The book has some examples, but let me suggest one that I see all the time…suppose you have bunch of datasets. How to you read them in. Use a for loop. So you create a list of the names of the data sets, then you work through the list and read each one it. What the for loop allowed you to do is for a small change in your code you have scaled your operation by however much.
namelist = ['Chase', 'Dave', 'Sarah', 'Spencer'] # creates the list "namelist"
# below, the word "item" is arbitrary. End the line with a colon.
for item in namelist: # goes through the items in the list one at a time
print(item) # indent this line exactly 4 spaces
# if there is code after this, we'd typically leave a blank line in-between
One thing to notice is the item which is a place holder. The specific name item has no attachment to anything, all it says is that as it works through each object in the list, its temporary name will be item. Here, try to change item to bloob and see what happens.
Here is a numerical calculation…this is common in scientific computing…
numlist = [4, -2, 5]
total = 0
for num in numlist:
total = total + num
print(total)
Now here is a string.
word = 'anything'
for letter in word:
print(letter)
Note how general this is. The key issue is that as long as the for loop is over an “itteratable” object, then this this will work. Ask your self, what itterable objects do we know.
Now this example below combines the for loop and a conditional
vowels = 'aeiouy'
word = 'anything'
for letter in word:
if letter in vowels:
print(letter)
Exercise. Take the list stuff = ['cat', 3.7, 5, 'dog'].
Write a program that prints the elements of stuff.
Write a program that tells us the type of each element of stuff.
Challenging. Write a program that goes through the elements of stuff and prints only the elements that are strings; that is, the print the elements where function type returns the value str.
Exercise. Consider the list namelist = ['Chase', 'Dave', 'Sarah', 'Spencer'].
Write a loop that goes through the list until it reaches a name than begins with the letter S. At that point it prints the names and exits the loop.
Loops over Ranges#
I think this is less important in data work. We need to know it though, so let’s work through it. The first thing to learn is the type range
range?
my_first_range = range(0,10,2)
type(my_first_range)
print(list(my_first_range)) # why do need to add a list() function in print function?
for number in range(1,5,2): # the variable "number" can be anything
print(number)
for number in range(1, 11):
square = number**2
print('Number and its square:', number, square)
List Comprehension#
The basic idea is to create implicit loops on itterable objects like lists (note it need not be a list, just something we can itterate on). We refer to this as list comprehensions. It is useful in certain circumstances and shows up a lot in Python code.
To understand list list comprehension, lets first remind our selves what a loop is doing
namelist = ['Chase', 'Dave', 'Sarah', 'Spencer']
for item in namelist:
print(item)
A list comprehension gives us more compact syntax for the same thing:
[print(item) for item in namelist]
Notices what this is doing:
First there are the square brackets, this means we are creating a NEW LIST
The first part within the brackes is the operation we want to perform on the old list. Here we want to print it.
Then after the operation on the “item” we describe the for operation, the variable, and then the itterable oject we want to grab from.
Essentialy what all this says is “do
operationonitemin the list”
Again, as with loops, the variable item is a dummy: we can use any name we wish. Replace item with your pet’s name to see for yourself.
Lets see some examples:
fruit = ['apple', 'banana', 'clementine'] # A list...
FRUIT = [item.upper() for item in fruit]
print(FRUIT)
We can also apply conditions within list comprehensions
fruit6 = [item for item in fruit if len(item)<=6]
fruit6
Exercise. Take the list of growth rates g = [0.02, 0.07, 0.07]. Write a list comprehension that multiplies each element by 100 to turn it into a percentage.
g = [0.02, 0.07, 0.07]
Exercise. Take the mixed type list [True, "2", 3.0, 4] and create a new list of the associated types.
h = [True, "2", 3.0, 4]
Final point about this: List comprehensions and related stuff are okay to use for simple cases. However, for more complicated situations, comprehensions be very hard to read and understand. Hence, a traditional for loop would be more appropriate.
Functions#
The key idea here is that rather than repeating the same lines of code over and over again. We can create a function that performs some distinct operation. This is a good strategy for a lot of reasons
Efficient in terms of writing code
It facilitates easy to read code
Avoids any debuging issue that may arise when you have to modify multiple lines of code in the same exact way (just change the code in the function).
Finally, it will give us insight to what is behind various packages that we will be using in the future…what are they just a collection of functions!
def hello(firstname): # define the function
print('Hello,', firstname)
A couple of things:
Similar syntax to for loops, if statements. Here we start with def (short for definition), then we create the name of the function and then any inputs…
Four spaces for all operations preformed by the function. If it does not have four spaces, it is not recognized as part of the function.
One more thing. We have only have to run this code cell once. Once we do so the function is in the namespace and is good to go.
hello('Chase')
hello([1,2,3])
ans = hello('Lenny')
print(ans)
whos
This shows us that the function is there and available.
Returning to the function above, how would I modify it to return a different message if firstname is not a string?
Now sometimes we want the function to return a value…this is how we do it.
def squareme(number):
"""
Takes numerical input and returns its square
"""
return number**2, number # this is what the function sends back
squareme(2)
x, y = squareme(2)
y
def value_one(): # define the function
return 1.0
value_one()
max?
def combine(first, last):
"""
Takes strings 'first' and 'last' and returns new string 'last, first'
"""
lastfirst = last + ', ' + first
return lastfirst # this is what the function sends back
both = combine('Chase', 'Coleman') # assign the "return" to both
print(both)
Exercise. Create and test a function nextyear that takes an integer year (say 2015) and returns the following year (2016).
Exercise. Create and test a function that takes a string year (say, ‘2015’) and returns a string of the next year (say, ‘2016’).
Exercise. Write a function that extracts the last letter from a string
Exercise. Use the function above and write a program so that last letter of each item in the list names = [‘Chase’, Dave’, ‘Sarah’, ‘Spencer’] is printed
Bonus (optional): Print the last letter only if it’s a vowel.
Objects#
This is a key feature of python…it’s an object oriented programming language. What does that mean? For us this means that every thing is really an object with associated methods and attributes. A method is like a function that already togo with the given object. Methods in python are always completed with () . Attributes are go-to-go attributes about the object that can be accessed easily. What this means is that there are simple built-in ways to get information and perform operations on objects without having to write our on functions.
Functions, methods, and attributes differ primarily in their syntax:
Syntax of a function:
function(object)Syntax of a method:
object.method()Syntax of a attribute:
object.attribute
We used the former in the previous section and will consider the latter here.
OK…but if I have say a list, how do I know the methods and attributes associated with it…here comes TAB completion which we covered in last Notebook.
whos
numberlist.append?
numberlist.append(7)
print(numberlist)
first_name = "Chase"
first_name.lower()
Exercise. This one also come up in our work. Suppose we have a variable z = ‘12,345.6’. What is its type? Convert it to a floating point number without the comma. Hint: Use tab completion to find a method to get rid of the comma.
Exercise. Take the list fruit and create a new list with the first letter capitalized. What method would you use to capitalize a string?
Exercise. Run the code
firstname = 'John'
lastname = 'Lennon'
firstlast = firstname + ' ' + lastname
Find a method to replace the n’s in firstlast with asterisks.
Exercise. Consider the following string x = "How many characters and words are in this string?"
How many characters does x contain?
Convert x to a list of individual characters.
Convert x to a list of individual words.
How many words does x contain?
Exercise (challenging). Use tab completion and the Object inspector to find and apply a method to the string name that counts the number of appearances of the letter s. Use name = ‘Ulysses’ as a test case.
Are their other ways of doing this????
name = 'Ulysses'
Exercise. Consider the dictionary names = {'Dave': 'Backus', 'Chase': 'Coleman', 'Spencer': 'Lyon', 'Glenn': 'Okun'}
Use tab completion to get all the keys.
What type is the output above. Can you convert this to a list.
With your list, write a for loop over it, pass the keys to the dictionary, and print out the values.
Summary#
Congratulations! First, it’s amazing that you have made it this far. Reflect on what you knew before working through this notebook, namely what we did in notebook 1. Now reflect on what you can do…AMAZING!!! Let us summarize some key things that we covered.
Boolean variable and its operations: We conduct the comparsion operation on the right: x = 3 > 2, and we can assign the boolean values (True or False) to the variable x. We also learned how to compare two strings.
“if” conditional statement: it allows us to do different things depending on the result of a comparison or Boolean variable.
Slicing: we learn Forward and Backward counting conventions in a list, do you know when to select which? We also cover using
:operator to select groups of data.“for” Loop:
We can use
forto loop through any iterable objects.We talk a common built-in iterable object/data sturcture:
rangeto help us with the data slicing/indexing.
Functions: we learn how to define and use customized functions.
Objects: a core concept in a object oriented programming language like python. It can help us understand how we can use
.operations to call methods and attributes in an object.