Jupyter notebook tutorials/Basics/Basics.ipynb
This is a quick review of some basic Python 3 features that you might use in your assignments. Of course, this is far from being exhaustive.
This tutorial follows a example-exercise format. Grey boxes are cells containing code - just place the cursor in any code cell you want to execute, then click on 'Cell/Run' or click on the "play" button.
Python is indentation-sensitive by design – so, please follow the left-indentation that I have used. Otherwise, you will receive an 'IndentationError'. It doesn’t have to be the exact same amount of indentation, however. For example, if you see a tab, it means that there needs to be some left-indentation there; it could be just a single space (tabs are preferred only for clarity). But if you don’t see any indentation, then there shouldn’t be any.
Any line that starts with a '#' is a comment, that is Python does not execute it.
Official Python documentation - https://docs.python.org/3/
A popular book “A byte of python" - http://www.swaroopch.com/notes/Python
BASICS
EXAMPLE 1
Variables & printing
Assigning values to variables, and printing them.
In Jupyter notebook, executing a block with just a variable name or a function output will automatically print the value.
EXERCISE 1.1
Assign numerical values to two different variables, multiply them, store the result in a different variable and print it.
"Concatenation"
This will be a running theme for the data types we look at: how to combine two elements of the type. Numberic types (int
and float
) are immutable in Python.
By analogy, you can probably figure out what the -=
and *=
operators do.
Comparison
EXERCISE 1.2
It is true that for a given integer N, N times N (N squared) is greater than or equal to N. Assign an integer to a variable and show this condition is true.
Numerical operations
Division, modulo, exponent
Yes, the all of the shorthand assignment operators work like you would expect
EXERCISE 1.3
Calculate the product of x and its reciprocal (1/x). Verify that the result is equal to 1.0
Functions
Defining functions with def
. Note the colon at the end of the arguments list.
Functions can have optional arguments as well
EXERCISE 1.4
Define a function called is_even
that uses the modulo operator to return whether or not a given integer is even. You'll know your function works if the assertions in the block after run without error.
EXAMPLE 2
Conditional logic
Note how the else-if is implemented in python – it is ‘elif’. Also, notice the colon at the end of the conditions which is part of the syntax.
EXERCISE 2.1
Write a function compare()
that accepts two values, and prints if the first value is greater, less than, or equal to the second value.
Example:
EXAMPLE 3
Loops
Again note the colon at the end of the loop statements.
Often used in loops, the range()
function allows iterating over a sequence of integers.
By itself, range()
gives an iterator; we can use list()
to iterate through it and return all of the values in a list.
EXERCISE 3.1
Using a loop, calculate the sum of first 10 positive integers (zero is not positive).
EXERCISE 3.2
Write a loop that goes through numbers 1 through 20, printing only the even numbers
EXERCISE 3.3
A natural number is prime if it has no positive divisors other than 1 and itself. Write a function is_prime()
that checks if a number is prime. The assertions afterwards should pass.
EXAMPLE 4
List
A list is a sequence of several (possibly unknown quanitity) similar objects. Use square brackets to define a list, and also to access elements by their index. Lists can have elements added to the end with append()
or inserted at an arbitrary index with insert()
. The del
statement deletes an item from a list. The len()
function returns the length of a list.
NOTE: All datatypes in Python have their indices starting from 0 as opposed to 1.
The built-in function sorted()
will return a sorted copy of a sequence, i.e. it doesn't change the original. Lists also have a .sort()
method that sorts in-place.
Concatenation
Concatenation of lists also works with the +
operator:
But since lists are mutable, we can also modify them in place with extend
:
Tuple
A tuple can be used to describe the various features of a single object. Suppose a person is to be identified just by their age. Then a simple scalar variable (like the variable x above) would suffice. If a person's name is to be included, then a tuple can be used to store such information. Indexing facility is available, if parts of a tuple must be retrieved. Use circular brackets/parantheses to define a tuple, but as with all sequences, square brackets to access values by their index.
Tuples are "immutable", meaning one can't delete, insert, or append items. As with all sequences, the len()
function does return the tuple's length.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-cc9e09edf93d> in <module>()
1 # This will raise an error
----> 2 del person_1[0]
TypeError: 'tuple' object doesn't support item deletion
Concatenation
Concatenation of tuples works with -- you guessed it -- the +
operator.
Since tuples are immutable, there is no in-place change but the +=
operator does work.
Notice that a 1-item tuple must have a trailing comma. The following version will fail:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-26-cf4bc4c4613a> in <module>()
1 # Raises a TypeError
----> 2 record += ('6 days ago')
3 record
TypeError: can only concatenate tuple (not "str") to tuple
Looping over sequences
In other C-like languages, looping over sequences is usually done by iterating over the indices like this:
We're more civilized here in Python world, so we can use this more readable syntax to loop over a sequence:
If you absolutely need the indices, use the enumerate()
function
EXERCISE 4.1
Create a list with the following numbers in the same order: 2,7,3,5,9,2,6,15,4. Using a loop, identify the indices in the list with numbers greater than 4. Have the loop insert these indices in a list as and when they are found, and print it at the end of the loop.
EXERCISE 4.2
Write a function reverse()
that takes a sequence and returns a list with the sequence items in reverse order. Use a loop for this, don't use the builtin .reverse()
method or the indexing trick in the following assertion.
Bonus: Don't use the range()
function either. It's unPythonic 😃
The assertion afterwards should pass.
Aside: Lists vs tuples -- what's the difference?
In addition to mutability, there is a "cultural" difference between tuples and lists. As shown in this example, lists are generally used when you have several items of the same "type", e.g. a list of names. If you're getting a list of names from a database query, for example, you may not know how many names are going to be returned.
Tuples are used when you have multiple different pieces of information about one "thing", e.g. a person's name and age. The cultural difference follows from the immutability of the tuple -- in the above tuple example, the 1th element is always the age, since we know there won't be an extra element inserted between the name and age. Thus a tuple is more like a single database row, with each value corresponding to a column.
When you're the one typing in the values, it usually doesn't matter much which one you use.
For more information on this, check out the excellent article by Ned Batchelder: http://nedbatchelder.com/blog/201608/lists_vs_tuples.html
Slicing
Slicing is used with the colon (😃 inside square brackets. The intution is returning the items at indices from a range()
command.
Negative indexes can be used to count from the end of the sequence
Like the range()
syntax, we can add a "count-by" argument
Sequence membership
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-40-f64f6f3f3203> in <module>()
1 # This will raise an error
----> 2 components.index('java')
ValueError: 'java' is not in list
EXERCISE 4.3
Create an intersect
function that takes two sequences and returns a new sequence consisting of the items contained in both sequences.
Example:
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-42-759d77f0a135> in <module>()
1 _test = intersect( [1,2,3,4], [3,4,5,6] )
----> 2 assert sorted(_test) == [3, 4]
3 # Yes, there's a better way to do this with sets...
AssertionError:
EXAMPLE 5
Strings
One of Python's most beloved qualities is its powerful string manipulation abilities. Strings are immutable sequences like tuples, thus have some of the same methods:
There are some nice capitalization methods
Concatenation
The + operator is used for string concatenation.
Since strings are immutable there is no in-place change, but the +=
operator does work:
EXERCISE 5.1
Create a very simple pig-latin translator function, simple_pig_latin()
. Put the first letter of the input string on the end and add '-ay'. The assertion afterwards should pass.
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-111-e981e3fa559b> in <module>()
----> 1 assert simple_pig_latin('clayton') == 'laytoncay'
AssertionError:
EXERCISE 5.2
Now make a better pig-latin translator pig_latin()
. Take all of the letters up until the first vowel and put them at the end, then add '-ay'.
EXERCISE 5.3
This is a classic. Write a function is_palindrome()
that takes a string as input and checks if it is a palindrome.
A palindrome is a word/sentence that reads the same forwards and backwards. Examples include 'racecar' and 'A man, a plan, a canal, panama'.
Your function should ignore spaces and capitalization, but don't worry about punctuation.
Bonus: Do this without using indices
Bonus: Do this without a loop
More string awesomeness
String formatting is a whole other subject, but here is the basic usage
The .replace()
method is useful. For a more flexible version of this, those interested can look up re.sub()
The .split()
method returns a list of items separated by the given string
The .join()
method is a bit unintuitive at first, but provides the inverse of .split()
EXAMPLE 6
Dictionary
A dictionary (dict
) can be used to store associations or relations between different entities (person and age, name and alias, person and friends' names etc.). Dict items are specified as key:value pairs within curly brackets. Instead of accessing dictionary values by their index, we use the key. As always, values are accessed using square brackets.
Since we check for key membership with 'in', it makes sense that list(age_data)
gives us all of the keys in age_data
This is one way to loop over a dict
The .items()
method gives us another way
The keys of a dict must be an immutable object e.g. string, number, or tuple.
The values of a dict can be anything, including lists:
and mutable values in dicts can be changed.
EXERCISE 6.1
A bored (and inaccurate) spy satellite makes a record of your vacation trail. Below are a few entries in its cloud storage:
Day 1: Paris, Lat = 99, Long = 100
Day 4: Prague, Lat = 99, Long = 90
Day 6: Zurich, Lat = 90, Long = 90
Day 10: Moscow, Lat = 80, Long = 70
Store the above information in a dictionary. Choose an appropriate key. Using a loop, produce a list of just the names of places visited after Day 2 and located above 85 latitude. Name this list matching_places
.
File I/O
Unrelated to dicts, but necessary for the exercises
There is a file called nato.txt
in this directory. It has one item on each line. The following piece of code does the a few things:
Opens the file for reading, assigning the file handle to the variable
f
Reads the entire contents of the file as a string with
f.read()
Splits the file content string by newlines, obtaining a the list of items
Implicitly closes the file handle once we leave the
with
block
NOTE There are a few methods of parsing a file into a list, one line to an item. The downside of this method is that it can produce an empty item at the end of the list:
Keep this in mind. One way to deal with it is when consuming the list, add a check like this:
EXERCISE 6.2
Create a lookup table for the NATO phonetic alphabet. Store it in a dict named nato
. The key should be the first letter of each item in the list.
EXERCISE 6.3
Write a function phonetic()
that translates a word or short sentence into the NATO phonetic alphabet. Your function should return a space-separated string. Ignore spaces and capitalization, but don't worry about punctuation.
"Concatenation"
Unfortunately you can't combine two dicts with the +
operator (by default, you could define it). Since dict
s are mutable, there is an in-place way to combine two dicts, using the update()
method: